Я изобретаю (квадрат) колесо? - PullRequest
3 голосов
/ 08 апреля 2011

Как мы должны знать, Clojure map может быть применен к последовательности:

(map #(* %1 %1) [1 2 3])           ; (1)

.. или к нескольким, таким образом:

(map vector [0 1] [2 1])           ; (2)
;=> ([0 2] [1 1])

ТеперьЯ хочу получить тот же результат, что и (2), но у меня есть аргументы, хранящиеся в последовательности.Другими словами, следующее не дает желаемого результата:

(map vector [[0 1] [2 1]])         ; (3)
;=> ([[0 1]] [[2 1]])

Итак, я написал этот простой макрос, где umap означает "unsplice map":

(defmacro umap [fun args-list]
  "umap stands for unspliced map.
  Let args-list be a list of args [a1 a2 ... an].
  umap is the same of (map fun a1 a2 .. an)"
  `(map ~fun ~@args-list))

Очевидно,это работает как шарм:

(umap vector [[0 1] [2 1]])        ; (4)
;=> ([0 2] [1 1])

Так вот мой вопрос: я изобретаю колесо?Есть ли другой способ сделать так же, как (4)?

Пока и спасибо заранее,

Альфредо

Ответы [ 3 ]

13 голосов
/ 08 апреля 2011

apply распаковывает все элементы в последовательности в конце списка аргументов.

user> (apply map vector [[0 1] [2 1]])
([0 2] [1 1])
8 голосов
/ 08 апреля 2011

Не совсем очевидно, что ваш umap работает как заклинание.Фактически, это будет работать только в том случае, если у вас есть вектор аргумента в качестве литерала во время компиляции - что в точности соответствует времени, когда вы могли бы передать несколько аргументов map в любом случае!

user> (umap vector [[1 2] [1 2]])
([1 1] [2 2])
user> (let [args [[1 2] [1 2]]]
        (umap vector args))
java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
[Thrown class java.lang.RuntimeException]

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

user> (let [args [[1 2] [1 2]]]
        (apply map vector args))
([1 1] [2 2])
0 голосов
/ 09 апреля 2011

Я что-то упустил, или mapcat работает для ваших нужд?

...