【发布时间】:2019-09-01 20:55:37
【问题描述】:
我正在尝试编写一个名为 different 的宏来测试两个用户提供的参数是否临时为 eq,其中参数可能是绑定的或未绑定的。但我迷失在可能性(也许还有逻辑)中。以下似乎可行,但需要增强(包括避免变量捕获和多重评估):
(defmacro different (item1 item2)
`(not (eq (if (boundp ',item1) ,item1 ',item1)
(if (boundp ',item2) ,item2 ',item2))))
基本思想是寻找任何未绑定的变量,引用它,然后查看它是否是eq 对另一个变量的值。 (目标是让最终用户不必决定何时引用参数,因为绑定变量会被标记。)
那么现在:
if x is unbound and y is bound to 'x, or
y is unbound and x is bound to 'y
(different x y) => NIL
if x is unbound and y is bound to 'z, or
y is unbound and x is bound to 'z
(different x y) => T
主要问题是 item1 或 item2 可以是任意 lisp 对象的指示符(在这种情况下,equalp 将替换为eq)。例如:
(defparameter x 3)
(different x 3) => NIL (since they are equalp)
(defparameter x '(a b c))
(different x (c b a)) => T (where (c b a) gets quoted)
这是否可以纳入宏中,是否可以将 if 语句放在反引号之外?
【问题讨论】:
-
请注意,BOUNDP 仅适用于特殊变量 - 不适用于词法变量。
-
EQ和EQUALP是什么关系? EQ 比较对象身份。 EQUALP 按值比较一些相同类型的对象,一些按内容比较,一些按 EQ...
-
我认为,如果你让这样的东西运行,你将创造出一种方法来迷惑任何接触使用它的代码的人。我的意思是,Perl 已经够混乱了,它只是在需要时在数字和字符串之间进行转换。您现在想要根据某些隐式全局状态在符号和由它们命名的变量的值之间进行转换。只是说。
-
@Svante。取点。但这一切都局限于一个宏。我现在看到的更大的问题(根据上面的 Rainer Joswig)是绑定变量总是词法的,所以 boundp 不起作用。对我来说,它仍然是一个值得/简化的用户界面,但我可以探索其他替代方案(或者只需要 lisp 代码)。
标签: variables macros common-lisp