的行为quote
在R6RS附录A.3中指定。对于'1
,相关规则是6sqv:
(存储 ( sf 1 ...) S 1 [ 'sqv 1 ]) → (存储 ( sf 1 ...) S 1 [ sqv 1 ])
是时候打破这个了。
“S → T”表示法定义了评估术语的一个步骤,其中“S”评估为“T”。
由于store
和非终结符在左侧和右侧看起来相同,因此您无需了解它们即可了解如何评估。如果您需要某些东西,请将其视为“存储环境”,并将其视为名称和值对;表示标识符与 value 相关联,并且在评估 term 时与之相关联。sf1
'1
store
sfn
(store ((x 1) (y 2)) S)
x
1
y
2
S
如果你不熟悉这个符号,它指的是一个有一个“洞”(一个里面有 a 的词)填充的术语。有两个相关的语法元素:带有孔的术语 ( ) 和带有由值填充的孔的术语 ( )。孔有点(但只有一点)像未命名的变量。一个重要的区别是一个术语只允许一个洞。孔可能最好用例子来解释。以下是:S[e]
[]
e
S[]
S[e]
S[]
请注意,只有在子项在语法上有效时才会出现空洞;[] 2)
不是一个有洞的术语。S[0]
将是一个0
代入洞中的术语:
当为孔指定值时,该术语S[]
也称为“上下文”。这来自 term-with-holes 的主要用途之一:匹配包含给定值的任何术语。是任何包含有效子术语的术语,因此出现的上下文也是如此。简而言之,它是包含引用的任何术语的替代。S[e]
e
S[]
e
S1['sqv1]
请注意,第二个术语为引用术语提供了两种不同的上下文:(list [] 'a "foo")
, (list 'bar [] "foo")
. 这表明您不应该过多地将漏洞视为未命名的变量。
如果您想知道为什么使用上下文术语和孔,它们是递归定义的替代方案。如果没有上下文,→ 必须在术语结构上递归定义(Scheme 的语法定义了结构)。lambda 演算中的替换是结构递归的一个示例,您可能在 Scheme 中定义的任何树处理函数也是如此(尽管 Scheme 语法与用于定义 → 和 lambda 演算替换的语法完全不同)。
(define (tree-depth tree)
(if (pair? tree)
(max (tree-depth (car tree))
(tree-depth (cdr tree)))
1
) )
接下来,让我们检查一下 的含义sqv
,它是“自引用值”的缩写。这是附录 A.2 中给出的Scheme 语法的非终结符。
平方::= n | #t | #f
n ::= [数字]
sqv只是一个数字或布尔值。
总之,6sqv评估规则意味着引用的数字或布尔值评估为数字或布尔值;报价被简单地丢弃。
这对您的作业意味着您无法区分普通函数1
和'1
普通函数之间的区别,因为在调用函数之前会评估子项。你需要一个宏。
为什么要经历这一切只是为了说“'1
评估为1
”?首先,回答“为什么”比回答“什么”更重要。此外,它有望帮助您超越问题,学习一点如何阅读 Scheme 的形式语义,让您体验计算理论概念并引发更多问题。