从字符串中读取表单时评估宏

Evaluating a macro when form is read from a string

我有一个宏with-voice:

(defmacro with-voice (tag body)
  `(format nil "<span class=\"~a\">~%~a~%</span>" ',tag ,body))

它会发出一些文本,这些文本被带有一些 class 的标签包围。我知道有像 CL-WHO 这样很棒的图书馆 - 但我只需要一些小东西......

CL-USER> (with-voice narrator "foo")
"<span class=\"NARRATOR\">
foo
</span>"

这是期望的结果

我希望能够从字符串中做到这一点

(let ((s (read-from-string "(with-voice narrator \"foo\")")))
  (print (eval s)))

这个有效:

CL-USER> (let ((s (read-from-string "(with-voice narrator \"foo\")")))
  (print (eval s)))

"<span class=\"NARRATOR\">
foo
</span>" 
"<span class=\"NARRATOR\">
foo
</span>

但它有可怕的 eval。我尝试使用宏和 lambda 来让它工作,但我无法让它工作。

我将不胜感激

谢谢!

你可以在阅读形式的某个位置调用你期望的符号:

(destructuring-bind (operator class text)
    (read-from-string "(with-voice narrator \"foo\")")
  (funcall operator class text))

或者甚至只是期望这些表单是可调用的:

(apply #'funcall (read-from-string "(with-voice narrator \"foo\")"))

如果您有更多不同形状的数据,您可能想要匹配这些数据,例如。 G。使用 optima,或使用 eql 专家的调度。如果读取的输入可能包含有害意图,这也有助于验证。