Scheme 为什么方案需要特殊的程序概念';谁的位置标签?

Scheme 为什么方案需要特殊的程序概念';谁的位置标签?,scheme,r5rs,r7rs,Scheme,R5rs,R7rs,为什么Scheme需要过程位置标签的特殊概念? 标准上说: 作为计算lambda表达式的结果而创建的每个过程 (概念上)标记有存储位置,以便 eqv?还有情商?制定程序 eqv?程序返回#t如果: obj1和obj2是位置标记相等的程序 情商?那么eqv呢?保证在…上有相同的行为。。。程序 但与此同时: 变量和对象(如对、向量和字符串)隐式表示位置或位置序列 eqv?程序返回#t如果: obj1和obj2是表示存储中相同位置的对、向量或字符串 情商?那么eqv呢?保证在…上有相同的行为。

为什么Scheme需要过程位置标签的特殊概念?
标准上说:

作为计算lambda表达式的结果而创建的每个过程 (概念上)标记有存储位置,以便 eqv?还有情商?制定程序

eqv?程序返回#t如果:

  • obj1和obj2是位置标记相等的程序
情商?那么eqv呢?保证在…上有相同的行为。。。程序

但与此同时:

变量和对象(如对、向量和字符串)隐式表示位置或位置序列

eqv?程序返回#t如果:

  • obj1和obj2是表示存储中相同位置的对、向量或字符串
情商?那么eqv呢?保证在…上有相同的行为。。。对。。。以及非空字符串和向量

为什么不将“隐式表示位置或位置序列”也应用于过程 我认为这也与他们有关

在这一点上,我看不出过程有什么特别之处。

对、向量和字符串是可变的。因此,这些物体的身份(或位置)很重要

过程是不可变的,因此它们可以被任意复制或合并,而没有明显的行为差异。在实践中,这意味着一些优化编译器可以内联它们,有效地使它们成为“多个副本”。R6RS特别指出,对于像

(let ((p (lambda (x) x)))
  (eqv? p p))
,因为它可以内联为
(eqv?(lambda(x)x)(lambda(x)x))


R7RS的位置标记的概念是确保表达式确实会导致true,即使实现进行内联。

对、向量和字符串是可变的。因此,这些物体的身份(或位置)很重要

过程是不可变的,因此它们可以被任意复制或合并,而没有明显的行为差异。在实践中,这意味着一些优化编译器可以内联它们,有效地使它们成为“多个副本”。R6RS特别指出,对于像

(let ((p (lambda (x) x)))
  (eqv? p p))
,因为它可以内联为
(eqv?(lambda(x)x)(lambda(x)x))


R7RS的位置标记的概念是确保表达式确实是真的,即使实现是内联的。

将过程视为值在像ML这样的语言中工作,它们是真正不可变的。但在Scheme中,过程实际上可以被变异,因为它们的局部变量可以被修改。实际上,过程是穷人的对象(尽管OO风格的对象也可能只是穷人的过程!)位置标记的用途与对象标识相同,它可以区分两对具有相同汽车和CDR的汽车


特别是,赋予全局过程标识意味着可以直接询问我们所传递的谓词是否为eq?还是eqv?在R6RS中是不可移植的(尽管在实践中R6RS实现中是可能的)。

将过程视为值在诸如ML这样的语言中工作,在这些语言中它们是真正不可变的。但在Scheme中,过程实际上可以被变异,因为它们的局部变量可以被修改。实际上,过程是穷人的对象(尽管OO风格的对象也可能只是穷人的过程!)位置标记的用途与对象标识相同,它可以区分两对具有相同汽车和CDR的汽车


特别是,赋予全局过程标识意味着可以直接询问我们所传递的谓词是否为eq?还是eqv?在R6RS中,这是不可能移植的(尽管在实际的R6RS实现中是可能的)。

想象一下斯大林的例子
(begin(define(f x)(lambda()x))(eq?(f 1)(f 2))
。程序相同,但闭包不同。我不清楚R7RS是否会对
#f
进行评估,因为我认为位置标记与源代码中的词法位置有关。@Sylwester每次调用
lambda
都会生成一个新的位置标记,而不是像您所说的源代码中的词法位置。:-)这类似于每次调用
list
生成新列表。想象一下斯大林
的例子(begin(define(fx)(lambda()x))(eq?(f1)(f2))
。程序相同,但闭包不同。我不清楚R7RS是否会对
#f
进行评估,因为我认为位置标记与源代码中的词法位置有关。@Sylwester每次调用
lambda
都会生成一个新的位置标记,而不是像您所说的源代码中的词法位置。:-)这类似于每次调用
list
生成新列表。