Как написано в другом посте, я пишу компилятор Shen в Clojure. Для этого мне нужен макрос/функция, которая получает символ как параметр, и если функция Shen привязана к ней, она возвращает функцию, и если символ определен как макрос Clojure, он должен вернуть макрос, поэтому ((function or) true false)
должен дать тот же результат как (or true false)
.Возврат макроса из макроса в Clojure
Мой макрос в настоящее время выглядит следующим образом:
(defmacro kl/function [x]
(cl/let [fn (symbol (cl/str (name x) "__fnPoF__"))]
(if (function? fn) `(eval ~fn) `(quote ~x))))
Постфиксное «__fnPoF__» есть из-за двойное пространство имен в Shen. (Значение и функции могут быть назначены одному и тому же символу.)
Моя проблема сейчас в том, что ((function or) true false)
оценивается как ложное, так как он оценивает, как ('or true false)
, но если я оставить из «цитата» (x
вместо `(quote ~x)
я получаю следующее исключение:
kl=> (function *)
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'kl/*, compiling:(NO_SOURCE_PATH:8)
ли кто-то есть идея, как решить эту проблему
Как я писал выше, если я заменю '' (quote x) 'на' x', я получаю 'CompilerException java.lang.RuntimeException: не могу взять значение макроса: # 'kl/*, compiling :(NO_SOURCE_PATH: 8) ' –
@NameLess Вау, это довольно интересно. Похоже, макроэкрандер видит, что '((function when) ...)' не имеет макроса в качестве своей первой подформы, поэтому он отказывается от макрорасширения. Затем, когда внутренняя вещь расширяется до 'когда', она не возвращается. Я не уверен, как вы с этим справитесь. – amalloy