(let [ x (or nil 4)
y (or 2 6)
z (or nil 10)]
(+ x y z))
=> 16
This use of 'or' is fairly idiomatic, and not just in Lispish. Less
typing than 'if'. And you can use it or not, unlike i-let, which
forces you to put in a default for all bindings.
Regarding the implementation of i-let, if the intention is as above,
then I'm guessing the macroexpansion of
(i-let [ x *something* 4] (* x x))
should be equivalent to
(let [x (or *something* 4)] (* x x))
However, in the given implementation, the decision is made at
macroexpansion time whether to expand to
(let [ x *something*] (* x x)) ;; expansion A
or
(let [x 4] (* x x)) ;; expansion B
and the decision is not made on the _value_ of *something* but on the
literal source code. Since in this case (binding 1) is *something*, a
Symbol and definitely not nil, expansion A will be chosen, independent
of the value of *something*. Easily fixed by embedding the if test
inside the let rather than the other way around. (And if I have
missed the point of i-let, please ignore all I've said.)
David
On Jul 27, 7:33 pm, nchubrich <[email protected]> wrote:
> I've been learning Clojure. I just wrote a macro to be used like so:
> (i-let [x nil 4
> y 2 6
> z nil 10]
> (+ x y z))
> => 16
>
> I.E. if the first value in the triple is nil, bind it to the second
> value in the triple. This is useful when you want to let something
> that might be nil and has a sensible default. (In practice I only see
> the need to do this \once, but I wrote it for multiple bindings for
> generality. And yes, I'm too lazy to type an if statement every
> time.)
> Here's the code:
>
> (defmacro i-let [bindings body]
> (assert-args i-let
> (vector? bindings) "a vector for its bindings"
> (= 0 (mod (count bindings) 3)) "forms by three in binding vector")
> (if (empty? bindings)
> `(let ~bindings ~body)
> (let [nom (bindings 0)
> attempted-val (bindings 1)
> nil-val (bindings 2)]
> (if (nil? attempted-val)
> `(let [~nom ~nil-val] (i-let ~(vec (drop 3 bindings)) ~body))
> `(let [~nom ~attempted-val] (i-let ~(vec (drop 3 bindings))
> ~body))))))
>
> Note that I've stolen the private code for assert-args----why, by the
> way, is this private?
> Anyway I'd appreciate any critiques of the implementation; whether
> it's a useful thing or not; if there are more idiomatic ways of doing
> the same thing; and, if yes-no to the aforetwo, where's the best place
> to add this functionality?
> I've really been enjoying this language (I come from a Scheme
> background). One stumbling block for me is the seq functions. I'd
> really like versions of them that preserve the underlying type (so
> that, for instance, in the above macro I could just write "(drop 3
> bindings)" instead of "(vec (drop 3 bindings))". What is the reason
> for them only returning a common type?
>
> Thanks,
>
> Nick Chubrich.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---