måning
Good Morning!
Good morning
Morning 🌄
I've started to see a bit more letfn
in my travels around the clojure codespace. Do people find them useful?
Not really. I rarely see them.
Good Morning ☀️ 🔥 💀
I use them from time to time; though often you end up needing a let
anyway if you need more non function bindings.
They can be good for implementing localised statemachines that close over some common bindings.
Unlike def
they support forward declaration, so they’re good at handling mutual recursion etc
e.g. forward declaration:
(letfn [(a [] (println :a) (b)) (b [] (println :b))] (a))
mutual recursion makes them quite good for parsers etc
morning
I don't think I've ever used a letfn
in production code
I see, so in a
you're forward referencing b
even although it's not defined just yet.
Would it be a considered a code smell? (apart from the usecase referenced by Rick)?
idk I tend to consider anything that's not super primitive a code smell haha
i try to write code that i can debug while tired, under stress cos prod is down
:D
:thumbsup:
Even though a let
in that case is arguably a little better I personally wouldn’t really consider it a code smell if it was a standalone letfn
it’s something I’d probably only change if you ended up needing to add new bindings that would mean you had something like (let [bar ,,,] (letfn [(foo [] ,,,)],,,))
in which case I’d wait till that point before refactoring it into (let [foo (fn [] ,,,) bar ,,,] ,,,)
Just checked and
https://github.com/bbatsov/clojure-style-guide
doesn’t mention letfn
(not even in issues) so it seems in eight+ years nobody has thought using it is particularly smelly
clj-kondo
also doesn’t seem to lint it as a potential smell either; though it does check it’s used properly…
clj-kondo
could easily check it was only used for forward declaration or mutually recursive uses; so if it’s something you care about, you could possibly open an issue on that repo for discussion.
I think the main argument against using it, is that it’s less familiar to people than let
and let
is more general; though some may consider the extra specificity of it as a benefit
Just scanned one of our larger code bases for uses of it, and it’s currently used in two places… none of which use it for forward declaration or mutual recursion…. both cases define it immediately at the top of the function definition to define a localised helper function that closes over some of the outer arguments; and that helper is repeatedly used multiple times within the body.
Personally I think this can be a good use of it, as the letfn
makes it very clear that the helper is local where as merging it into the let
it wraps would hide the helpers important role.
I tend to just define the helper at the top of a regular let since there's usually other bindings
tho i'm sure you can find examples in code where i totally break that rule
I would use letfn
for mutually recursive functions, not for anything else
would you consider adding a lint for it to clj-kondo?
well, it's not bad to use it, just unnecessary. I think a warning might be a bit too much
Yeah that’s my feeling too
it’s not particularly hard to read; and it’s not very commonly used anyway
Thanks everyone! A very informative disscussion!
possibly sacrilige here but I'm enjoying peering into purescript JS dev
halogen is p like re-frame
you can really see the ML <-> lisp connection in the DSL
morning
I have looked into Haskell and Purescript with Halogen a lot last year and in the end I found myself fighting against the typechecker a lot. I was really excited about this whole idea of explicit side effects until I tried to build actual software 😄
yeah that's largely been my experience too
but although I love re-frame I've often found cljs pretty difficult to love (although shadow has massively improved that tbf) and types in node land make a fair bit of sense, as well as being able to do monadic stuff around asyncs and whatnot
Morn
Bro it's 5.30pm
We run UGT here, so morning is perfectly fine
But I think he's in Cambridge 😂
that is the beauty of UGT, it doesn't matter where you are.
Oh I wasn't aware of Universal Greeting time
nor where anyone else is
Good morning then
that is ok.... instead of having the conversation of morning... no here where I am it is not morning we just discuss UGT instead
🙂
Yep, that's pretty much how it works 😃... @zyxmndaleyjes ;)...