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 (mkinc 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)))