【问题标题】:Distinguishing Bound from Unbound Variables区分绑定变量和未绑定变量
【发布时间】: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


【解决方案1】:

只有六种情况需要处理

这里是要做的事情的映射:

For b ≡ bound symbol
For u ≡ unbound symbol
For e ≡ any other value
b b -> eq
b u -> equalp
u u -> equalp
e e -> equalp
e u -> ERROR (makes no sense)
e b -> equalp

希望这可以帮助您组织分支逻辑。当我遇到这样的爆炸时,我喜欢拉一些纸并通过分支工作。通常可以使用谓词演算来减少它,或者提出另一种分支更少的表示。

【讨论】:

  • 感谢您分析 Spenser。查看您的列表后,似乎它可能会进一步简化。 (但如果知道这是否误解了一些基本的 lisp 概念,将不胜感激。)也许传递给宏的参数可以分为绑定符号(也称为变量)和其他所有内容,它们是任意 lisp 对象(非变量)。然后,非变量可以分为对自己求值的那些(数字、字符、向量、函数、哈希表等),以及那些不求值的(例如,x、'x、(a b c)、'(a b c)等)。
  • 因此,如果评估宏参数产生错误,那么它是一个非变量。如果它对自身求值,那么它也是一个非变量。但是,如果它对自身以外的东西求值,它就是一个绑定变量。这是否有意义并且值得尝试编写代码?
猜你喜欢
  • 2022-12-10
  • 2016-06-14
  • 2018-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 2014-04-01
相关资源
最近更新 更多