(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 -~----------~----~----~----~------~----~------~--~---