2009/7/28 David Miller <dmiller2...@gmail.com> > > (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. >
Unless you want the default value for a non initialized boolean value to be true ... (let [x (or false true)] => whooops > > 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 -~----------~----~----~----~------~----~------~--~---