(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 <nicholas.chubr...@gmail.com> 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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to