Clojure - как правильно применять функции в последовательности к аргументу?

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

Это связано с тем, как Lisp-подобный язык различает 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 ответа

Решение

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

(-> 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)))) чтобы понять почему.

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

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

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

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

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

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

(|> x h g f) ; equal to f(g(h(x)))
Другие вопросы по тегам