Fork me on GitHub

Hi, why do I have to write: (->> {} (#(assoc % :x 3))) instead of (->> {} #(assoc % :x 3))


(def x #(assoc % :version 3))


(->> {} x) works too without the parens.


The doc of ->> says ”

Inserts x as the
last item in the first form, making a list of it if it is not a
list already.
It shall make it a list if not already is.


so shall it be with #(assoc )


The reason is that #(assoc % :x 3) is read as a function, not a list


It is equivalent to writing (fn [m] (assoc x :x m))


And you can see how threading to that won't work


> The reason is that `#(assoc % :x 3)` is read as a function, not a list I see. It is read as a list. so the value inserted is INSIDE the function list form.


But when you have the extra parentheses around, you get a list with a function in the first position, and argument last.


(macroexpand '(->> {} #(assoc % :x 2)))
=> (fn* [p1__18483#] (assoc p1__18483# :x 2) {})
here you see that the map {} ended up inside the function body, which is not as intended

thanks3 1
Bob B00:10:40

just as an add-on, in this situation, the thread-first macro might be clearer/preferred:

(macroexpand '(-> {} (assoc :x 3)))
=> (assoc {} :x 3)


Unless you have a pipeline of just sequence functions (map, filter, etc), it is pretty much always better to start off with -> since you can use all the other arrow functions inside -> (including ->> and as->).


> since you can use all the other arrow functions inside `->` (including `->>` and `as->`). Can you be more specific?


(-> x
  (->> (map inc))
  (as-> y (if (seq y) y 0)))

👍 2
Tim Abdulla18:10:27

are protocol implementations transitive? e.g. I have a namespace A that requires namespace B that in turns requires namespace C. in namespace C, a protocol implementation is defined for String. will that implementation be defined in A by virtue of having included B?

Alex Miller (Clojure team)18:10:18

yes, that will work (although transitivity is the wrong model)

Alex Miller (Clojure team)18:10:36

a protocol is a global extension space

Alex Miller (Clojure team)18:10:19

you need to load the code (via require or elsewise) that provides the extension before the point where you use it

Tim Abdulla18:10:43

transitivity is the wrong model because its global, not transitive?

Tim Abdulla18:10:50

or I guess, transitive by virtue of being global

Alex Miller (Clojure team)18:10:57

it doesn't matter what namespace the extension is in, or how you got there, just that it's loaded before use

Alex Miller (Clojure team)18:10:36

that is, C is not providing it to B who's providing it to A, so there is no transitivity


Hi. I'm looking at core.memoize, say I'm trying to memoize different functions that each takes a map as an arg. The maps are relatively complex, say a couple levels of nesting, includes collections as values etc. Does care need to be taken to account for potential ordering differences within the map? Or is there some magic that handles this out the box? I see there's an args-fn option I could pass, so that would work, some general recursive sorting fn perhaps. Many thanks


As this is the beginners channel, can you explain which collection's ordering you are talking about? Some things are unordered and you might be assuming they have an order versus others that actually have an order (like lists and vectors).


Ah good point, let's assume ordered collections are used as values in the map. I guess what I'm concerned about is either these collections are sorted differently, or the entires in the map are in different “order”


it should stand out as kind of tautological but order is important for ordered collections

🙂 1

On the other hand, a sorted collections can compare equal to its equivalent unsorted type


Sure. I was more curious how the memoize fns behaved with these kind of things - ill try some examples tomorrow. Thanks!


I think ultimately that will depend on what cache you're using and how it does the lookup


@U0HJAJ64E The argument list is used as a key into the hash map of cached argument lists to get the computed value. So the equality behavior is identical to Clojure's built-in hash map key lookup/insertion (and therefore key collision/comparison machinery).


Depending on how deep down the rabbit hole you want to go:

Muhammad Hamza Chippa22:10:39

how to generate uuid from string ?

Alex Miller (Clojure team)22:10:16

(java.util.UUID/fromString s)

🙌 1

If you're asking for Clojure (on the JVM), it's typical to use the Java standard library via interop for that sort of thing ☝️:skin-tone-2:

🙌 1