This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-01-03
Channels
- # aleph (2)
- # announcements (6)
- # babashka (6)
- # beginners (106)
- # biff (8)
- # clara (24)
- # clj-kondo (10)
- # clj-otel (4)
- # cljdoc (2)
- # clojure (54)
- # clojure-conj (3)
- # clojure-europe (85)
- # clojure-norway (54)
- # clojure-uk (3)
- # clojurescript (27)
- # community-development (2)
- # data-science (1)
- # datahike (2)
- # datomic (11)
- # deps-new (67)
- # emacs (4)
- # graalvm (15)
- # hyperfiddle (11)
- # introduce-yourself (1)
- # lsp (6)
- # malli (30)
- # midje (4)
- # nrepl (13)
- # off-topic (86)
- # polylith (7)
- # releases (2)
- # sql (10)
Hello! Is it possible to skip the caching of certain values when using clojure.core.cache.wrapped/lookup-or-miss
? Specifically I want to skip caching when value-fn
is not able to compute the value. I don't want to cache failures. I was thinking on throwing an exception, but I don't know if it's idiomatic.
In my case value-fn
is not a pure function. It depends on some external calls. So not getting the right answer from those systems for example
I meant, how would anything external to value-fn
determine that it has failed?
Throwing an exception has the failure semantics built in, and judging by the code, doing so should be fine.
Returning some sort of status is another approach, but then you have to make the caching functionality be aware of it. Seems like one way (the only way?) to do it is to make a cache wrapper with defcache
that delegates all functions to the wrapped instance but has an extra check in miss
.
Ok, I wil throw then. I guess is the simplest approach. Thanks!
Hey guys. I have troubles with tools.build. When I run the uberjar with java -jar
, I get:
Could not find or load main class secret_sauce.server.main
Caused by: java.lang.ClassNotFoundException: secret_sauce.server.main
All the details are at
https://gist.github.com/jakub-stastny/103ed2fc5f3f021312bb7c5e474dd612
Thank you 🙏try this :main 'secret-sauce.server
in args for uber
it should point to the namespace where you define -main function
That did it. Thank you!
what I have done many times when I want to avoid many bindings is (loop [{:keys [x y z] :as state} init-state] ... (-> state (update :x inc) (recur)))
and the like. i.e. use a map
what it suppose to return? [10 10 10]?
@U05224H0W nice, but feels more busy visually, harder to see what’s going on
maybe instead of a vector for recur you can use some sort of placeholder as "unchanged value"
something like (recur _ (inc y) 0) or (recur _ (inc y))
but at the end this is hardly different from (recur x (inc y) 0)
@U08JKUHA9 do you have some example in mind?
Well any time you have more than 2-3 variables in the loop @U04V4KLKC
I don't agree with just using a map. A lot of the time when loop is used, performance is important, so you wouldn't want to just leave speed on the table.
if there are more than 2-3 variables it is just a question of typing a bit more, filling recur forms with variable names. However, I can see one specific usecase where loop+ form might help — refactoring by adding one more variable into the loop bindings. In case all recur forms know loop context they do not require any changes.
I agree with the second part there, though not with the premise that 'it is just a bit more typing' is a good reason to not add it. That is the case with so many features that are already in Clojure that you probably think are worth it.
I simply can't justify implicit scope in that case. To me it is very similar to implicit function arguments:
(def y 2)
(defn foo [x y]
(+ x y))
(foo 1)
;; => 3
this is also some sort of shorten form of
(defn foo
([x] (foo x 3))
([x y] (+ x y)))
loop and its binding vector can be seen as an anonymous function declaration and recurs in its body "just" calling that function with potentially different arguments. I know that in reality it is a bit more complex than that. but this mnemonic doesn't let me down yet) now let's consider loop+ where recur can be "called" with less arguments than required by loop bindings. that means those calls evaluate in the scope of arguments passed to the previous call to "the same function". this scope is implicit and most likely hard to manage. this is what I tried to explain by my last example where I consider a single iteration with scope coming from the namespace.
The use-case of “refactoring loop by adding one more member and now I have to change all recurs” is exactly what I had in mind (and in practice)
I also kind of like that arguments to recur now have names, so it’s easier to see what is bound to what
@U04V4KLKC you can think of it as a let expression that is evaluated before going into the loop
this is exactly as I was thinking about it 😜
btw, refactoring use cases are worth reporting to clojure-lsp folks
@U050UBKAA have you seen my first suggestion? wdyt? https://clojurians.slack.com/archives/C03S1KBA2/p1704300490836949?thread_ts=1704291917.720089&cid=C03S1KBA2
It has the same problem: if I add one more loop argument I’ll have to change all recurs. Also, positional binding becomes unmanageable really quick (4+ arguments are already too much)
in this form you can omit rest unchanged args (recur x) instead of (recur x _)
i wish we had access to local macros. i know there's tools.macro, but it would be nice to have them built in. https://github.com/clojure/clojure/commit/00f9c7b50c1b17af85fa58d1d8ac4f4027e88177
macrolet has some issues though
(letfn [(foo [x] (inc x))]
(clojure.tools.macro/macrolet [(m [x] `(foo ~x))]
(m 2)))
Syntax error compiling at (REPL:196:3).
No such var: user/foo
that implementation has issues, yeah. if it was built in, those issues would be possible to avoid
objective? obstacle?
objective: i want a macro that closes over local variables and isn't available outside of the current scope. Same goals as writing (let [foo (fn ...)] (foo ...))
Not every function needs to be a generally available function with a name. "Anonymous" functions are useful. Macros are similarly useful, and letting them be locally scoped would make it easier to write one-off macros without polluting the current namespace
I agree with that. I like really expressive macros in tests and I don’t want to invite others to use it. It’s a local that makes the code (almost always tests) more expressive. But it’s not fully general and no other namespaces should use it
so another available solution is a private macro that takes args for your local vars, right?
there are many solutions, and that is one i've used before. it's more cumbersome than a locally defined macro and requiring a "unique" name leads to not using a macro at all, more often than not
heh I'm reminded of Guido Van Rossum's comments (poorly remembered) about lambdas in Python: "if you need more than one line, define a function"
feel free to post on ask clojure (but please try to highlight the problem, rather than "local macros", which is one possible solution)
i'm just chatting lol, i know to ask for anything specific on ask
clojure's design philosophy is "macros as tool of last resort", and not including local macros or symbol macros aligns with that pretty firmly
this came from wondering if could i could just define a let-bound macro and see if it would work. then when it didn't, i looked at the code to see why isMacro
wasn't finding the metadata. the linked line above explains it