开发者

Clojure -- what is the correct way to apply functions in sequence to an argument?

I'm not clear on the difference between -> and ->> in Clojure: from the API reference, it seems like the latter would be the correct way to apply several functions in sequence, i.e. (->> x h g f) would result in f(g(h(x))).

This is related to how Lisp-like language differentiate f(x, y) and (f(x))(y), whereas Haskell does not, correct? (Using math notation; commas intended to imply n-ary functions, not tupling).

Thanks in advance!

Edit

I'm wrong, neither work except on simple functions like (def inc #(+ 1 %)), where they both work.

Here's an example of a function that doesn't work with -> or ->>,

(defn mkinc­ [amnt­] (fn [x] (+ x amnt)­))
(-> 3 (mkin­c 2))
; ERROR -- Wrong number of args (2) passed to: sandbox58780$fn--58797$mkinc
((mkinc 2) 开发者_开发百科3)
; 5


-> and ->> are equivalent if all the functions take only one argument. Otherwise, -> passes the value being threaded as the first argument to the function where as ->> passes it as the last argument. The following example should make this clear:

(-> x
    (f 1 2)
    (g 3 4)
    (h 5 6))

becomes

(h (g (f x
         1 2)
      3 4)
   5 6)

or h(g(f(x, 1, 2), 3, 4), 5, 6)

(->> x
     (f 1 2)
     (g 3 4)
     (h 5 6))

becomes

(h 5 6
   (g 3 4
      (f 1 2 x)))

or h(5, 6, g(3, 4, f(1, 2, x)))

Edit: (Responding to the Edit in the question, copying this from the comments).

The example doesn't work because the -> macro inserts the 3 as the first arg of mkinc. See (macroexpand-1 '(-> 3 (mkinc 2))) to understand this better.

This does work: (-> 3 ((mkinc 2))). See (macroexpand-1 '(-> 3 ((mkinc 2)))) to understand why.


-> inserts the prev form into the 2nd position. Whereas ->> inserts into the last position. Taking a page from Joy of Clojure, note the insertion point marked by ,,,

(-> x (f ,,, 1) (g ,,, 2) (h ,,, 3))

(->> x (f 1 ,,,) (g 2 ,,,) (h 3 ,,,))


In case there's no solution, I managed to hack it with syntax macros,

(defmacro fwcomp [& fcns] `(comp ~@(reverse fcns)))
(defmacro |> [x & fcns] `((fwcomp ~@fcns) ~x))

Usage:

(|> x h g f) ; equal to f(g(h(x)))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜