Clojure - Каков правильный способ применения функций последовательно к аргументу?
Я не понимаю разницу между ->
и ->>
в Clojure: из ссылка API, кажется как и последний, было бы правильным способом применить несколько функций последовательно, т.е. (- → xhgf) приведет к f (g (h (x))).
Это связано с тем, как Lisp -образный язык дифференцирует f (x, y) и (f (x)) (y), тогда как Haskell не исправляет? (Использование математической нотации, запятые, предназначенные для обозначения n-арных функций, а не чередующиеся).
Спасибо заранее!
Изменить
Я ошибаюсь, не работаю, кроме простых функций, таких как (def inС# (+ 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
Ответы
Ответ 1
->
и ->>
эквивалентны, если все функции принимают только один аргумент. В противном случае ->
передает значение, которое передается как первый аргумент функции, где as ->>
передает его в качестве последнего аргумента. Следующий пример должен сделать это ясно:
(-> 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
- > вставляет предыдущую форму во вторую позицию. Принимая во внимание, что → > вставляется в последнюю позицию. Взяв страницу из Радости Clojure, отметьте точку вставки, отмеченную ,,,
(-> x (f ,,, 1) (g ,,, 2) (h ,,, 3))
(->> x (f 1 ,,,) (g 2 ,,,) (h 3 ,,,))
Ответ 3
В случае отсутствия решения мне удалось взломать его с помощью синтаксических макросов,
(defmacro fwcomp [& fcns] `(comp [email protected](reverse fcns)))
(defmacro |> [x & fcns] `((fwcomp [email protected]) ~x))
Использование:
(|> x h g f) ; equal to f(g(h(x)))