【发布时间】:2019-04-26 11:51:16
【问题描述】:
如何在宏中引入新的、可预测命名的带有后缀的标识符?
所以,我正在编写一个用于操作四元数的简单库。我暂时使用了可能可行的最简单的表示形式,即组件列表,但我想定义一个不依赖于该表示形式的简单 API。
在定义算法时,我想使用可预测的名称来引用四元数的每个组件,例如 somesymbol-realpart 或 somesymbol-i。
我希望能够让以下 sn-p 工作。
(let
((my-quat '(1 2 3 4)))
(with-quaternion my-quat
(assert-equalp 1 my-quat-realpart)
(assert-equalp 2 my-quat-i)
(assert-equalp 3 my-quat-j)
(assert-equalp 4 my-quat-k)))
但是,我用于生成带有后缀的符号的方法似乎会生成带有转义大写字符的奇怪的区分大小写的符号。
(defun add-suffix-to-symbol (sym suffix)
(intern (concatenate 'string "" (string sym) "-" suffix)))
作为将符号转换为字符串的结果,它以大写形式打印...这是完全有效的规范化。但是,由于某种原因,通过intern 创建新符号会保留大小写,因此我必须执行以下操作来引用with-quaternion 引入的绑定。
(let
((my-quat '(1 2 3 4)))
(with-quaternion my-quat
(assert-equalp 1 |MY-QUAT-realpart|)
(assert-equalp 2 |MY-QUAT-i|)
(assert-equalp 3 |MY-QUAT-j|)
(assert-equalp 4 |MY-QUAT-k|)))
如何创建一个与旧符号相同但带有后缀的新符号,以便可以在宏中使用?
供参考,这里是所有代码。
(defun assert-equalp (e a)
(assert (equalp e a)))
(defun quat-realpart (q)
(first q))
(defun quat-i (q)
(second q))
(defun quat-j (q)
(third q))
(defun quat-k (q)
(fourth q))
(assert-equalp '1 (quat-realpart '(1 2 3 4)))
(assert-equalp '2 (quat-i '(1 2 3 4)))
(assert-equalp '3 (quat-j '(1 2 3 4)))
(assert-equalp '4 (quat-k '(1 2 3 4)))
(defun add-suffix-to-symbol (sym suffix)
(intern (concatenate 'string "" (string sym) "-" suffix)))
(print (add-suffix-to-symbol 'a "suffix"))
(defgeneric with-quaternion-impl (q-sym body))
(defmethod with-quaternion-impl ((q-sym symbol) body)
(let
((q-realpart (add-suffix-to-symbol q-sym "realpart"))
(q-i (add-suffix-to-symbol q-sym "i"))
(q-j (add-suffix-to-symbol q-sym "j"))
(q-k (add-suffix-to-symbol q-sym "k")))
`(let
((,q-realpart (quat-realpart ,q-sym))
(,q-i (quat-i ,q-sym))
(,q-j (quat-j ,q-sym))
(,q-k (quat-k ,q-sym)))
(progn ,@body))))
(defmacro with-quaternion (q-sym &rest body)
(with-quaternion-impl q-sym body))
(let
((my-quat '(1 2 3 4)))
(with-quaternion my-quat
(assert-equalp 1 |MY-QUAT-realpart|)
(assert-equalp 2 |MY-QUAT-i|)
(assert-equalp 3 |MY-QUAT-j|)
(assert-equalp 4 |MY-QUAT-k|)))
(let
((my-quat '(1 2 3 4)))
(with-quaternion my-quat
(assert-equalp 1 my-quat-realpart)
(assert-equalp 2 my-quat-i)
(assert-equalp 3 my-quat-j)
(assert-equalp 4 my-quat-k)))
当在clisp 下运行时,它会打印以下符号,清楚地带有转义的大写字符。
|A-suffix|
并产生以下错误消息:
*** - PROGN: variable MY-QUAT-REALPART has no value
【问题讨论】:
标签: common-lisp