Передача списка переменных индивидуально в функцию clojure - PullRequest
4 голосов
/ 15 декабря 2011

Я играл с clojure и решил создать функцию более высокого порядка, которая комбинирует mapcat и list для эмуляции этого поведения:

Clojure> (mapcat list '(1 2 3 4) '(5 6 7 8))
(1 5 2 6 3 7 4 8)

моей первой попыткой было определение mapcatList следующим образом:

Clojure> (defn mapcatList[& more](mapcat list more))
#'sandbox99/mapcatList
Clojure> (mapcatList '(1 2 3 4) '(5 6 7 8))
((1 2 3 4) (5 6 7 8))

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

Clojure> (defn mapcatList[x y & more](mapcat list x y))
#'sandbox99/mapcatList
Clojure> (mapcatList '(1 2 3 4) '(5 6 7 8))
(1 5 2 6 3 7 4 8)

Это решение хорошо работает с двумя списками, но я бы хотел, чтобы функция работала с переменным числом аргументов.

Мой вопрос: как я могу передать переменное число аргументов функции, а затем деструктурировать их так, чтобы они передавались как отдельные аргументы вместе в «список mapcat»?

Ответы [ 2 ]

14 голосов
/ 15 декабря 2011

Вы ищете apply. Это вызывает функцию с аргументами, предоставленными в последовательности.

Но знаете ли вы, что есть функция interleave, которая делает именно то, что пытается сделать mapcatList?

5 голосов
/ 15 декабря 2011

Вы правы, аргументы обернуты в список в результате объявления vararg.Вам нужно apply аргументы, чтобы развернуть список аргументов:

(defn mapcatList[& more]
  (apply mapcat list more))

user=> (mapcatList '(1 2 3 4) '(5 6 7 8))               
(1 5 2 6 3 7 4 8)
user=> (mapcatList '(1 2 3 4) '(5 6 7 8) '(\a \b \c \d))
(1 5 \a 2 6 \b 3 7 \c 4 8 \d)
...