does anybody else feel great regret when they need to resort to as->
?
it's bitten me when i want to mix map/reduce/filter with other functions that don't follow that same format
maybe I'm missing something, even. i'll paste it next time i run into it
I think ideally it's used when you have a single operation in a thread-first chain of operations that has a different/weird signature
(-> {}
(assoc :x 3)
repeat
(as-> x (take 5 x))
(conj :hello))
This is a pretty horrible example, and ->>
would work better here anyway. The clojure core functions tend to be designed to avoid these situtions. But I do hit this in the wild sometimes.This is an actual real world example I used it in lately where I needed to pass the same request data around internally ina lot of places. A let
might be better here too but I think this is a place where as->
is ok
(as-> req-vec x
(ibg/add-id conn x)
(ibg/add-default-args x)
(ibg/req-tap conn x (a/chan 1 (comp (ibg/sync-xf x) (ibg/payload-xf x))))
(a/into [] x)
(a/<!! x))
ah yeah last last second last last. it'd be nicer if there were a way to override this in the nested form itself somehow
that's probably a world of pain to do, though
i often find myself wanting to make a #()
that gets threaded into a ->
. i wonder if that's legit
I recently replaced an awkward usage of as->
with cond->>
Before:
(as-> main it
(parse-string it)
(if format (with-msg "formatting" (reformat it)) it)
(if snap (with-msg "snapping" (snap-to-grid it to-closest min-margin)) it)
(stringify it)
(assemble front it)
(spit file-path it)))))
After:
(-> (parse-string main)
(cond->>
format (with-msg "formatting" reformat)
snap (with-msg "snapping" #(snap-to-grid % to-closest min-margin)))
(->> (stringify)
(assemble front)
(spit file-path))))))
cond->>
and cond->
were new to meβ¦oh i see. needing "it" in both branches of the if
yeah that's a bummer
i don't think i've used cond->>, myself
You can use #()
if you just wrap it in parens
(-> 123
(#(inc %))
((fn [x] (str x))))
not pretty but i use this in the repl sometimesOh I see you meant starting with the function
yeah it feels like some hack just to keep the consistency of the ->
alas, it's not stopped me from using it! π
There was some sort of related discussion on clojureverse recently on some alternative threading macros https://clojureverse.org/t/looking-for-opinion-about-some-macro-ive-been-working-on/4782/19
oh wow
so diamond wand looks like what i've been missing. where if you don't include a <>
in the nested forms it defaults to the behavior of the non-diamond version
(as-> coll $
(map transform-data $)
(filter filter-data $)
(doseq [item $]
(println item)))
That's where I think the as->
macro shines. When you're using it with something like doseq where none of the other thread macros would work.the diamond wand doesn't seem to work here:
(-<>> data
(map identity)
(filter (constantly 1))
(doseq [item <>]
(println item)))
as->
must do nested replacements where -<>>
doesn't, i guess