Fun with Macros: If-Let and When-Let
stevelosh.com
Fun with Macros: If-Let and When-Let
1–10 of 31 posts
Re: Fun with Macros: If-Let and When-Let
#2Why not use `if` and `when` directly? Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern?
I must be missing something.
Re: Fun with Macros: If-Let and When-Let
#3What’s a example of these macros being used usefully? All I can find are contrived examples. Why not use `if` and `when` directly? Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern? I must be missing something.
(let ((result (do-some-calculation)))
(when result
(operate-on result)))
`when-let' would just skip one "layer" of code, and I believe avoid assigning a local variable if (do-some-calculation) fails. Just a convenience.(edit: trying to fix formatting)
Re: Fun with Macros: If-Let and When-Let
#4What’s a example of these macros being used usefully? All I can find are contrived examples. Why not use `if` and `when` directly? Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern? I must be missing something.
if(auto p = get_ptr()) ...
And Rust: if let Some(value) = get_opt() ...
The latter, permitting arbitrary pattern matching, is especially useful and a common idiom.Re: Fun with Macros: If-Let and When-Let
#5What’s a example of these macros being used usefully? All I can find are contrived examples. Why not use `if` and `when` directly? Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern? I must be missing something.
This seems an awful lot like saying "Why use functions? All that they are doing is giving new names to variables" (although, to be very clear, I realise that there are meaningful differences between the two). To be sure, nothing can be done with these macros that could not be done without them—that's proven by the fact that they are coded as macros in a language that doesn't natively provide them—but it might be harder to read or write, or … whatever metric you value. I think that experience shows that any binding facility that is offered will make someone's programming life happier (although maybe many somebodies' debugging lives less happy).
Re: Fun with Macros: If-Let and When-Let
#6What’s a example of these macros being used usefully? All I can find are contrived examples. Why not use `if` and `when` directly? Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern? I must be missing something.
They're pure convenience, but they're pretty convenient. It's very common to have patterns like: (let ((result (do-some-calculation))) (when result (operate-on result))) `when-let' would just skip one "layer" of code, and I believe avoid assigning a local variable if (do-some-calculation) fails. Just a convenience. (edit: trying to fix formatting)
Re: Fun with Macros: If-Let and When-Let
#7What’s a example of these macros being used usefully? All I can find are contrived examples. Why not use `if` and `when` directly? Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern? I must be missing something.
I find them pretty useful in Clojure. Note that it’s practically never about assigning a strictly boolean-valued expression (which would indeed be pretty useless) but rather something that is ”truthy” or ”falsy” ie. implicitly convertible to boolean and you want to do something with the actual value if it is truthy. Other languages have similar constructs, eg. C++: if(auto p = get_ptr()) ... And Rust: if let Some(val…
To your parent, the RFC is pretty short and has good motivation: https://github.com/rust-lang/rfcs/blob/master/text/0160-if-l...
Re: Fun with Macros: If-Let and When-Let
#8What’s a example of these macros being used usefully? All I can find are contrived examples. Why not use `if` and `when` directly? Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern? I must be missing something.
Ultimately it's a convenience macro. Saves you a nesting level.
Re: Fun with Macros: If-Let and When-Let
#9Re: Fun with Macros: If-Let and When-Let
#10What’s a example of these macros being used usefully? All I can find are contrived examples. Why not use `if` and `when` directly? Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern? I must be missing something.
Sure, here are a couple examples I found from grepping my src directory.
roguelikelike game I made for a game jam: https://github.com/sjl/vintage/blob/master/src/main.lisp#L19...
prolog compiler: https://github.com/sjl/temperance/blob/master/src/compiler/3...
cl port of robotfindskitten: https://github.com/sjl/sattyrday/blob/master/src/002-afk/mai...
generative art lib: https://github.com/sjl/flax/blob/master/src/drawing/api.lisp... https://github.com/sjl/flax/blob/master/src/looms/004-turtle...
There are plenty of other things that use various versions of these macros too. ASDF uses them all over the place. And of course Clojure code uses their versions. A Github search for when-let and if-let will give a lot of examples (though you have to wade through all the import matches... unfortunately Github search doesn't let you search for literal strings like "when-let (" to exclude those).
> Why not use `if` and `when` directly?
Convenience, especially when you have multiple in a row:
(when-let ((a (foo))
(b (bar))
(c (baz)))
(blah a b c))
; =>
(let ((a (foo)))
(when a
(let ((b (bar)))
(when b
(let ((c (baz)))
(when c
(blah a b c)))))))
> Is creating new names for variables — which is what `if-let` and `when-let` seems to contribute — that common of a pattern?I'm not sure what "new names for variables" means here. `let` (and these convenience macros) defines local variables. People create local variables for things pretty often.