Clojure - как правильно применять функции в последовательности к аргументу? - PullRequest
11 голосов
/ 16 июня 2011

Мне не ясно, в чем разница между -> и ->> в Clojure: из справочника API кажется, что последний будет правильным способом применения нескольких функций в последовательности,то есть (- >> xhgf) приведет к f (g (h (x))) .

Это связано с тем, как Лисп-подобный язык дифференцируется f (x, y) и (f (x)) (y) , тогда как Haskell этого не делает, верно?(Использование математических обозначений; запятые предназначены для обозначения n-арных функций, а не кортежей).

Заранее спасибо!

Редактировать

Я не прав, ни одна из них не работает, кроме как напростые функции, такие как (def inc # (+ 1%)), где они оба работают.

Вот пример функции, которая не работает с -> или ->>,

(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

Ответы [ 3 ]

21 голосов
/ 16 июня 2011

-> и ->> эквивалентны, если все функции принимают только один аргумент. В противном случае -> передает значение, являющееся нитью в виде аргумента first , в функцию, а ->> передает его в качестве аргумента last . Следующий пример должен прояснить это:

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

становится

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

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

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

становится

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

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

Редактировать : (Отвечая на Редактировать в вопросе, копируя это из комментариев).

Пример не работает, потому что макрос -> вставляет 3 в качестве первого аргумента mkinc. См. (macroexpand-1 '(-> 3 (mkinc 2))), чтобы лучше это понять.

Это работает: (-> 3 ((mkinc 2))). См. (macroexpand-1 '(-> 3 ((mkinc 2)))), чтобы понять, почему.

3 голосов
/ 16 июня 2011

-> вставляет предыдущую форму во 2-ю позицию.Принимая во внимание - >> вставляет в последнюю позицию.Взяв страницу от Joy of Clojure, обратите внимание на точку вставки, помеченную ,,,

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

(->> x (f 1 ,,,) (g 2 ,,,) (h 3 ,,,))
1 голос
/ 16 июня 2011

В случае отсутствия решения мне удалось взломать его с помощью синтаксических макросов,

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

Использование:

(|> x h g f) ; equal to f(g(h(x)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...