This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-26
Channels
- # babashka (16)
- # beginners (38)
- # calva (11)
- # cider (35)
- # clj-kondo (3)
- # clj-otel (3)
- # clojure (28)
- # clojure-europe (11)
- # clojure-gamedev (14)
- # clojure-norway (42)
- # clojure-spec (4)
- # datalevin (10)
- # datomic (2)
- # emacs (8)
- # events (2)
- # fulcro (3)
- # gratitude (5)
- # hyperfiddle (3)
- # kaocha (1)
- # nbb (14)
- # nrepl (12)
- # portal (1)
- # re-frame (5)
- # releases (1)
- # shadow-cljs (36)
- # squint (167)
Is there a nice idiom or core function for when you have a collection of functions and you want to apply them in turn to a value, transforming that value as it cascades through the functions? Silly example:
(def fs [inc inc dec inc])
(loop [n 5 fs fs]
(if (seq fs)
(recur ((first fs) n) (rest fs))
n))
;; => 7
I'm imagining something like the threading macros, but where the functions you thread through are determined dynamically.here’s a clue:
(let [fs [inc inc dec inc]
n 5]
(reduce #(%2 %1) n fs))
(defn thrush [& args]
(reduce #(%2 %1) args))
(thrush 5 inc inc dec inc)
a couple of styles here :)
Ah, interesting! Thanks for the link. He uses comp
in reverse, too. I was thinking it's sort of a reduce
, but I just couldn't get my head around the fact that I'm not "folding" the functions themselves, but making a pipeline.
I guess that works though: the accumulator is the thing being transformed, which seems so obvious now that I see it.
user=> (doc comp)
-------------------------
clojure.core/comp
([] [f] [f g] [f g & fs])
Takes a set of functions and returns a fn that is the composition
of those fns. The returned fn takes a variable number of args,
applies the rightmost of fns to the args, the next
fn (right-to-left) to the result, etc.
that's what i would do over trying to understand what thrush
means in a codebase. composition is straightforward. thrush is non-standard. certainly understandable but there's a built-in idiom
You'd need to reverse fs
before comp
ing though, right? In this case, it doesn't matter, but in general the above would apply the transformations backwards.
I like the reduction a bit better for that reason: less moving parts
hi, is there any way to specify a return type hint for a function as clojure data structure? in this case a map :
(defn returns-a-map [a b]
{:arg1 a :arg2 b})
(defn returns-a-map ^Type [a b]
{:arg1 a :arg2 b})
You can specify returned type as a hint by adding it to the args vector. But in most cases you don't need to type hint functions that return clojure datastructures. Could you share in which context you think it is needed?I want to load a config file, which is file containing a clojure map
(defn load-config!
"Returns the content of config file as a clojure data structure"
[^String config]
(let [config-path (.getAbsolutePath (io/file config))]
(try
(read-string (slurp config-path))
(catch java.io.FileNotFoundException e
(log/info "Missing config file" (.getMessage e)
"\nYou can use --config path_to_file to specify a path to config file")))))
hm... type hints are useful only together with java interop. For example:
(defn foo ^java.util.Properties []
(java.util.Properties.))
(.setProperty (foo) "qwe" "qwe")
I don't think you need type hints at all in your example
oh, ok, thank you:slightly_smiling_face:
Are you using typehints as a "type system" marks for your code?
I'm asking because there are few libraries that offers much better features to cover validation: clojure spec, malli, plumatic schema, etc.
I am using type hints for documentation mostly and code readability, in this case another lib it is too much 🙂 thanks
The type hints are just metadata, not enforceable, so liable to rot like doc strings
hi, how to treat with clojure.lang.PersistentArrayMap ? i have a clojure map like this: {:connection #object[org.postgresql.jdbc.PgConnection 0xbf260d0 org.postgresql.jdbc.PgConnection@bf260d0]} and i want to print the value for :connection
you are seeing it printed. A postgres connection is a complicated object and it just prints out it’s type and hashcode
Oh, ok. How can i “expand” this object and extract data from it (eg. Host, port..etc)?
https://javadoc.io/doc/org.postgresql/postgresql/42.2.5/org/postgresql/jdbc/PgConnection.html
the connection itself probably doesn’t have a notion of host and port. But i suspect where you got the connection does
Hello, I was looking into possibility could cause memory issue and found this https://ask.clojure.org/index.php/10532/memory-leak-using-the-default-method-of-a-multimethod if i understood right defmethod :default shouldn't be used because it can cause permanent leak? How to deal with this then ?
> I don’t know if this is a leak so much as a design assumption that the number of dispatch values is bounded.
it’s a tradeoff. each time it sees a new value that dispatches to the default case it remembers that in order to be faster in the future (so it doesn’t have to recompute that it dispatches to the defaul). If you dispatch on reference identity objects, you’ll have this issue. Not with value based identity objects though.
;; reference based
(= (Object.) (Object.))
false
parse-test=>
;; value based
(= [] [])
true
user=> (defmulti f :foo)
#'user/f
user=> (dotimes [_ 10000000] (f (java.util.HashMap. {:foo 1})))
nil
would be the repro fram that ticket and im’ not seeing an OOMthe method cache is a map from dispatch value (output of the dispatch function) to a function
Oh i get it. Thanks a lot for the explanation. So this should be safe from that issue
(defmulti receive-feed :sportcode)
(defmethod receive-feed :default [msg]
(timbre/info "Ignoring feed message - unsupported title"))
(defmethod receive-feed "CS" [msg]
;;whatever
)
Because it's a value based and i don't expect infinite amount of variations in :sportcode
i won't run into this issue.it is a cache for all successful dispatch values, so this can be an issue any time there are an arbitrary number of successful dispatch values. if there is a default method, then all values are successful dispatch values so that may increase the likelihood of this being an issue. in practice, most uses of defmultimethods use a small number of dispatch values.
is there an easy way to get the cardinality of the cache? I’d be interested to see if we’ve got some cache build up we haven’t noticed
that methodCache field isn't public, but you could use reflection to go after it
or connect with a debugger