Правильная форма для макроса, который вы хотите написать, следующая:
(defmacro sym-def [s v] `(def ~(eval s) ~v))
... или эквивалентно:
(defmacro sym-def [s v] (list `def (eval s) v))
Вам просто нужно оценить первый аргумент внутри макроса, потому что аргументы макроса не оцениваются, когда он применяется. Если вы собираетесь использовать только выражения, производящие символы, это вызовы symbol
, вы можете предпочесть следующий макрос:
(defmacro defsym [s v] (list `def (symbol s) v))
... и компаньон к нему:
(defmacro sym [s] (symbol s))
Эти макросы переводят строку или символ в символ. Вот несколько примеров их использования:
(defsym "the first natural number" 0)
;=> #'user/the first natural number
(sym "the first natural number")
;=> 0
(defsym pi 3.14159) ;same as: (def pi 3.14159)
;=> #'user/pi
(sym pi) ;same as: pi
;=> 3.14159
Варианты, приведенные ниже, также могут быть полезны:
(defmacro defsym* [s v] (list `def (symbol (eval s)) v))
(defmacro sym* [s] (symbol (eval s)))
Они переводят строковое / символьное выражение в символ после его оценки. Вот несколько примеров использования defsym*
:
(defsym* "abc" "xyz")
(defsym* (str \a \b \c) "xyz")
(defsym* (symbol "abc") "xyz")
(defsym* 'abc "xyz")
;all the previous are equivalent and what follows is valid for any of them
;=> #'user/abc
abc
;=> "xyz"
(defsym* abc 0)
;=> #'user/xyz
abc
;=> "xyz"
xyz
;=> 0