(неравнодушный применяют ул.), и применять-ул. в clojure's->

Если я делаю следующее:

user=> (-> ["1" "2"] (partial apply str)) 
#<core$partial__5034$fn__5040 clojure.core$partial__5034$fn__5040@d4dd758>

... Я возвращаю частичную функцию. Однако, если я связываю его с переменной:

user=> (def apply-str (partial apply str))
#'user/apply-str
user=> (-> ["1" "2" "3"] apply-str)       
"123"

... код работает, поскольку я предназначил это. Я предположил бы, что они - то же самое, но по-видимому который не имеет место. Кто-то может объяснить, почему это мне?

5
задан Jason Baker 5 April 2010 в 01:45
поделиться

5 ответов

-> - это макрос, поэтому он не должен следовать правилам, которые вы ожидаете с точки зрения применения. Макрос преобразует источник перед оценкой форм. Попробуйте макрорасширение форм:

user> (macroexpand '(-> ["1" "2"] (partial apply str)))
(partial ["1" "2"] apply str)

Чего вы здесь пытаетесь достичь с помощью макроса '->'?

РЕДАКТИРОВАТЬ: Обратите внимание, что:

user> ((partial apply str) ["1" "2"])
"12"
6
ответ дан 18 December 2019 в 10:43
поделиться

Макрос -> добавляет скобки вокруг apply-str во второй версии, поэтому макрос расширяется для кода, который в конечном итоге вызывает вашу функцию. Посмотрите на исходный код для -> , и вы увидите:

(defmacro ->
  "Threads the expr through the forms. Inserts x as the
  second item in the first form, making a list of it if it is not a
  list already. If there are more forms, inserts the first form as the
  second item in second form, etc."
  ([x] x)
  ([x form] (if (seq? form)
              (with-meta `(~(first form) ~x ~@(next form)) (meta form))
              (list form x)))
  ([x form & more] `(-> (-> ~x ~form) ~@more)))

Соответствующая часть - это когда он имеет дело с двумя аргументами, x и формой . Если форма является последовательностью, x вставляется в качестве второго аргумента в этот список. В противном случае макрос помещает форму и x в сам список. Это сделано для того, чтобы вы могли использовать пустой символ как сокращение для списка, содержащего один символ.

user> (macroexpand '(-> 123 (foo)))
(foo 123)
user> (macroexpand '(-> 123 foo))
(foo 123)
0
ответ дан 18 December 2019 в 10:43
поделиться

Вам вовсе не обязательно это делать.

(->> ["1" "2" "3"] (apply str))

Почему бы не сделать это вместо этого?

5
ответ дан 18 December 2019 в 10:43
поделиться

Первое выражение, (-> ["1" "2"] (частично применить str)) , заменяется на:

(partial ["1" "2"] apply str) , что в основном означает:

Создайте функцию из ["1" "2"] (которая также является функцией, поскольку векторы являются функциями индексных ключей!) С помощью Vars apply и str уже указаны в качестве первых двух аргументов. Эта функция печатается как странная строка # . Только когда эта функция будет вызвана, вы получите исключение IllegalArgumentException, поскольку векторы принимают только один целочисленный аргумент, а не два аргумента Var.

4
ответ дан 18 December 2019 в 10:43
поделиться

Макрос -> Передает выражение через формы в качестве второго аргумента. В вашем случае заканчивается расширением до: (partial ["1" "2"] apply str) , создавая четную функцию на основе вектора.

Но вы хотите вызвать четную функцию, основанную на apply и str в многопоточном выражении, и, следовательно, вам необходимо:

(-> ["1" "2"] ((partial apply str)))

Что ж: этот код довольно запутанный и не идиоматический Clojure.

1
ответ дан 18 December 2019 в 10:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: