On Thu, Nov 15, 2012 at 5:17 PM, Alan Malloy <a...@malloys.org> wrote: > The primary point of let-> is that you can insert it into an existing -> > pipeline. > > (-> foo > (stuff) > (blah) > (let-> foo-with-stuff > (for [x foo-with-stuff] > (inc x)))
This use case of the macro now renamed as-> in Clojure 1.5 is already covered by using fn in a pipeline: (-> foo (stuff) (blah) ((fn [foo-with-stuff] (for [x foo-with-stuff] (inc x))))) A benefit of using fn here is that it also works with ->> just the same. However, there is a place for a construct to simplify multiple uses of fn in a pipeline like in: (-> foo (stuff) (blah) ((fn [foo] (for [x foo] (inc x)))) ((fn [foo] (for [x foo] (dec x))))) I propose fn-> as name for a construct similar to as-> used like this: (-> foo (stuff) (blah) ((fn-> [foo] (for [x foo] (inc x)) (for [x foo] (dec x))))) The fn-> macro defines an anonymous function using the same syntax as fn, with its forms threaded like in as-> where each evaluated form is bound to a symbol. In the example above, the result of the first 'for' form is bound to the 'foo' used by the second 'for' form. That is, within fn-> the items in the list bound to foo is first incremented and the resulting list bound to foo, then the items in the list bound to foo is decremented with the resulting list returned (incidentally leaving the list as before). Keeping the syntax and semantics of fn-> similar to fn provides an smooth upgrade path from current uses of fn in pipelines. -- Terje Norderhaug > On Thursday, November 15, 2012 10:35:59 AM UTC-8, Alex Nixon wrote: >> >> Hi all, >> >> I find the proposed function let-> in Clojure 1.5 very useful, but a bit >> ugly. The arguments are backwards when compared to vanilla let, and it >> doesn't support destructuring where it easily could (which I believe would >> be helpful when threading 'state-like' maps, as I find let-> very useful >> for). >> >> I'd like to float an alternative implementation which improves on both >> these issues. Thoughts? >> >> (defmacro new-let-> >> "Establishes bindings as provided for let, evaluates the first form >> in the lexical context of that binding, then re-establishes bindings >> to that result, repeating for each successive form" >> [bindings & forms] >> (assert (vector? bindings) "binding must be a vector") >> (assert (= 2 (count bindings)) "binding vector must contain exactly two >> forms") >> `(let [~@bindings >> ~@(interleave (repeat (bindings 0)) (drop-last forms))] >> ~(last forms))) >> >> (new-let-> [{:keys [foo bar] :as state} {:foo 1 :bar 2}] >> (assoc state :foo (inc bar)) >> (assoc state :bar (inc foo))) ; => {:foo 3, :bar 4} >> >> -- >> Alex Nixon >> >> Software Engineer | SwiftKey >> >> al...@swiftkey.net | http://www.swiftkey.net/ -- 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