Вызов функции Clojure со строкой внутри swap? - PullRequest
2 голосов
/ 04 ноября 2011

Макрос, transform!, как определено ниже, похоже, работает для => (transform! ["foo" 1 2 3]). Цель состоит в том, чтобы взять список, причем первый элемент представляет собой строку, представляющую функцию в пространстве имен. Затем оборачиваем все в swap!.

Проблема в том, что transform! не работает для => (transform! coll), где (def coll ["foo" 1 2 3]). Я получаю это тайное исключение:

#<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Symbol>

Функция:

(defmacro transform! 
" Takes string input and update data with corresponding command function.
"  
  [[f & args]]  ;; note double brackets
 `(swap! *image* ~(ns-resolve *ns* (symbol f)) ~@args))

Мне кажется странным, что это работает для одного случая, а не для другого.

Ответы [ 2 ]

5 голосов
/ 04 ноября 2011

Макросы работают во время компиляции и работают с кодом, а не с данными времени выполнения. В случае (transform! coll) макросу передается единственный, не оцененный аргумент: символ coll.

На самом деле вам не нужен макрос; Достаточно обычной функции:

(defn transform! [[f & args]]
  (apply swap! *image* (resolve (symbol f)) args)))

Разрешение переменных во время выполнения может рассматриваться как запах кода, поэтому подумайте, действительно ли вам это нужно.

0 голосов
/ 04 ноября 2011

Вы передаете символ макросу, а именно coll. Он попытается отделить этот символ в соответствии с оператором деструктурирования [f & args], что, конечно, будет невозможно.

Вы также можете использовать ( разрешение символ) вместо (ns-resol * ns * symbol).

...