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

Reply via email to