#clojure
#clojure
Вопрос:
В JavaScript можно выполнить следующее:
function foo(arg1, arg2, arg3) {
...
}
var others = [ 'two', 'three' ];
foo('one', ...others); // same as foo('one', 'two', 'three')
В Clojure «переменные аргументы» могут быть приняты следующим образом:
(defn foo [arg1 amp; others]
...)
Но чтобы передать их в сочетании с другими аргументами, вы должны сделать это:
(apply foo (concat '("one") others))
Что, честно говоря, действительно уродливо. Это также невозможно, когда вам нужно повторить:
(apply recur (concat '("one") others)) ;; doesn't work
Есть ли лучший способ сделать это? И если нет, есть ли вообще какой-либо способ выполнить это в recur
случае?
Ответ №1:
Но чтобы передать их в сочетании с другими аргументами, вы должны сделать это:
(apply foo (concat '("one") others))
Вам не нужно этого делать: apply
также является переменной функцией, которая может принимать аргументы перед конечным аргументом последовательности, например
(apply foo "one" others)
Вы можете передать любое количество отдельных аргументов перед конечным аргументом последовательности в apply
.
user=> (defn foo [arg1 amp; args] (apply println arg1 args))
#'user/foo
user=> (apply foo "one" 2 "three" [4 "five" 6.0])
one 2 three 4 five 6.0
Для дальнейшей демонстрации эти вызовы
функционально эквивалентны:
(apply 1 2 [3])
(apply 1 [2 3])
(apply [1 2 3])
Это также невозможно, когда вам нужно повторить
recur
это специальная форма, и apply
она не работает с ней так, как с обычной функцией Clojure.
есть ли вообще какой-либо способ выполнить это в
recur
случае?
Не с apply
помощью . Вы можете recur
использовать переменные аргументы, но вы не можете (apply recur ...)
.
Комментарии:
1. «Вам не нужно этого делать: apply также является переменной функцией, которая может принимать аргументы перед последним аргументом последовательности, например
(apply foo "one" others)
, вы можете передать любое количество отдельных аргументов перед последним аргументом последовательности для применения». Но развеothers
в этом случае не было бы передано как список, и его члены не были бы «сплющены» в оставшиеся слоты аргументов?2.@brundolf в этом случае
others
его члены были бы сглажены / распределены по оставшимся позициям аргументов.(apply 1 2 [3 4])
эквивалентно(apply 1 [2 3 4])
и(apply [1 2 3 4])
.3. Странно. Какой там точный алгоритм? Конечно, это не может быть «сглаживать каждую последовательность, переданную для применения»? Возможно, «сгладить последний аргумент, если это последовательность»?
4. @brundolf В основном предполагается, что последний параметр представляет собой список. Любые другие аргументы перед ним и после аргумента функции рассматриваются как элементы для
cons
добавления в список аргументов.5. Это вполне возможно с
recur
помощью . Учитывая(defn f [x amp; xs] ...)
, есть две переменные, которые необходимо передать любомуrecur
вызову:x
иxs
. Вам не нужноapply
, потому что компилятор точно знает, на какую арность отправляется (текущая). Таким образом:(defn f [x amp; xs] (if foo 0, (recur (inc x) (rest xs)))(