This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-02-03
Channels
You know what might be nice? An thread macro that can optionally escape forms, like (-> n dec #esc #(- 9 % 1) inc)
such that, instead of the value being threaded into the beginning or end of the anonymous function, the fn is allowed to convert itself into its evaluated form, and the thread sees it as a one arg fn.
Why wouldn't you just use as->
for that? (-> n dec (as-> n (- 9 n 1)) inc)
Seems to me that as->
is the "escape" function...
(-> n dec (as-> % (- 9 % 1)) inc)
if you prefer %
for the argument name.
(-> n dec #esc #(- 9 % 1) inc)
it's not all that different -- and it's built-in, no language extensions needed
(-> n dec #~(- 9 % 1) inc)
that might look prettier... and I wouldn't have to switch between two different thread macro contexts
Meh... you've saving so few keystrokes, and introducing non-standard syntax... I see no benefit.
(-> n (- 3) dec (->> (assoc state :n)) keys)
(-> n (- 3) dec (as-> % (assoc state :n %)) keys)
(-> n (- 3) dec #~#(assoc state :n %) keys) ; more cryptic and only one character shorter?
I hear you, I'm not completely sold on it either... I'd have to kick the tires on it some more.
And I'm not saying add a reader macro for #~
language wide. Just add another thread macro that detects it, like -#>
or something
Code golf. Doesn't make code any clearer.
Don't get me wrong, I find (partial f a b)
to be annoyingly long, as well as (comp f g)
, compared to Haskell's auto-currying and therefore f a b
and f . g
but it really isn't worth messing up the language syntax for a few characters of typing...
It's not about saving characters. It's about semantic context switching between various thread macro semantics
We're going to disagree on that.
I find this much more readable than your proposal (-> n (- 3) dec (->> (assoc state :n)) keys)
Especially when written indented:
(-> n
(- 3)
dec
(->> (assoc state :n))
keys)
There's also a strong argument that such long threads are inherently hard to read already and should be broken into named segments with let
...
hmmm. perhaps the idea could be further generalized and simplified... Perhaps -#>
could just evaluate all anonymous functions defined within the thread first ... then it's just (-#> n #(- 9 % 3) dec #(assoc state :n %) keys)
Personally, I think that's horribly ugly. It's not even consistent.
You're mixing an implicit ->
with regular anonymous functions 😞
It makes sense though... It's a thread macro that auto-evaluates anonymous functions first.
It doesn't make sense to me. It's horrible.
I know you're just saying that to goad me into writing a library for it... And I'm not gonna do it!
(as-> n % (- 9 % 3) (dec %) (assoc state :n %) (keys %))
is also horrible but at least it's consistent (and, hey, already possible/legal in Clojure).
well, I guess that -#>
is pointless, since it's basically just doing function application, just unwinding it, for less parenthesis
Consistency has had me recently move to wrapping all the forms in ( .. )
in a threaded macro BTW.
So I'm more likely to write:
(-> n
(- 3)
(dec)
(->> (assoc state :n))
(keys))
The more code I maintain, the more consistency and simplicity have come to matter.
And we're at
Clojure source 280 files 65913 total loc,
Clojure tests 320 files 22004 total loc,
these days.(nearly 88k lines... that's quite shocking to me, really, given where we were just a few years ago!)
No lein
, no boot
. Just clj
and deps.edn
these days too.
(and, of course, Clojure 1.10 in production, and testing against 1.11 master 🙂 )
I guess that last -#>
I described is really comp>
. It reverses the order of comp, so it reads like definition order, but allows you to thread in forms in the comp that are not functions.
Like transducers? 🙂
:rolling_on_the_floor_laughing:
so when i notice I'm Doing It Again i rewrite the whole thing with lets to see which is simpler
When it comes to weird threading macros, this library is funny https://github.com/rplevy/swiss-arrows
My issue with using let
s instead of threading macros is it allows me to write more procedural/pythonic code, instead of finding a functional way to write it
I’ve been working on a lot of ETL pipelines recently, so extracting my complicated let
conditionals into functions I can thread has been very helpful in maintaining the functional mindset
To store clojure data structures in a database (postgresql in my case), would you just store the EDN representation or encode it with transit?
@hmaurer using transit json-pretty gives you the option to query it in the future if you please.
When I try to require a namespace in the REPL but it fails because of a syntax error in said namespace’s file, how can I reload it after correcting the error? running require again throws a “namespace not found” error
@hmaurer https://clojuredocs.org/clojure.core/require see :reload
and :reload-all
I have probably a silly question:
(let [foo (my-macro)]
...)
I want my-macro
to know that it has been bound to the symbol foo
in this context.
Impossible, yes?OK, followup: is there any way (hacky or otherwise) to get at the let bindings inside of a function?
I have a lib where I’d like to provide some report of how it’s used inside of an opaque function
using some fancy tricks I can show what was passed in when the library functions were invoked, and the order of invocation, but I’m losing some semantics because there’s no names attached to them
[ANN] com.cognitect.aws/api-0.8.243 is released: https://groups.google.com/forum/#!topic/clojure/wzEy8tSSKF0
@lilactown you can get the line number with (-> &form meta :line)