第一个表达式在 Chez 9.5.4 中引发了一个异常,这是最新版本:
> (cond #t (else 2))
Exception: invalid syntax (cond #t (else 2))
Type (debug) to enter the debugger.
我不确定为什么 9.5.5 在这方面会有所不同;cond
如果属实,这可能表明9.5.5中的底层实现发生了变化。
在任何情况下,表单cond
都需要一个或多个<cond clause>
参数,以及一个可选else
子句,其中 a<cond clause>
必须是(<test> <expression1> ...)
; 即,a<cond clause>
必须是一个带括号的表达式,包含一个测试表单和零个或多个表达式。每个<cond clause>
都按顺序计算,直到 a<test>
计算结果为真,之后按顺序计算后续表达式,并返回最终表达式的值。如果 true 中没有后续表达式,则返回<cond clause>
的值。<test>
该表达式(cond #t (else 2))
违反了这一点(因为第一个<cond clause>
格式错误)并且可能会引发语法错误,9.5.4 会这样做。如果 9.5.5 在这种情况下没有引发语法错误,则可能应该向维护人员提交错误报告。再次注意,9.5.5 不是 Chez Scheme 的发布版本。
这已经在上面说明了,但我将在此重复:当一个<test>
表达式的计算结果为真,并且在 中没有后续表达式时<cond clause>
,该子句的计算结果为<test>
。因此,这有望根据 R6RS 工作,并且在 9.5.4 中按预期工作:
> (cond (#t) (else 2))
#t
这也是表达 OP 问题中第二个表达式的正确方法。在这里,我修改了该else
子句以3
使其更清楚地评估哪个分支:
> (cond ((> 2 1)) (else 3))
#t
> (cond ((> 1 2)) (else 3))
3
需要明确的是:<cond clause>
上面第一个表达式中的第一个是((> 2 1))
,其中包含. 该测试的计算结果为,并且由于该子句中没有后续表达式,因此该子句返回。第二个表达式有as its , 和. 此测试评估为,因此评估继续进行下一个, ,它返回。<test>
(> 2 1)
#t
#t
((> 1 2))
<cond clause>
<test>
(> 1 2)
#f
<cond clause>
(else 3)
3
问题中发布的未更改的第二个表达式在 9.5.4 中的行为方式与 OP 针对 9.5.5 报告的方式相同。此行为与 R6RS 指定的完全相同:
> (cond (> 2 1) (else 2))
1
这里的第一个是<cond clause>
形式(> 2 1)
,其中,和>
是and 。现在,如果计算结果为 true,则计算后续表达式,并返回最终表达式的值。<test>
2
1
<expression1>
<expression2>
<test>
因此,对于(cond (> 2 1) (else 2))
,第一个<cond clause>
是(> 2 1)
,其中<test>
是表达式>
,它的计算结果是一个过程,它不是#f
一个真值,因此是一个真值。然后依次对后面的表达式2
和求值,最终表达式的值为,然后返回。1
1
请注意,此处的表单(> 2 1)
未评估为 a <test>
;单独的表单>
被评估为<test>
. 此外,在这种情况下的(< 2 1)
行为应该相同。(> 2 1)
事实上,只要第一个元素的计算结果不为 ,任何类似的形式都会表现得与此相同#f
:
> (cond (> 2 1) (else 3))
1
> (cond (< 2 1) (else 3))
1
> (cond ('any-truthy-thing 2 1) (else 3))
1
版本更新
在我发布这个答案几天后,新版本的 Chez 发布了。请注意,OP 使用的是 9.5.5,它从来都不是发布版本(大概 OP 从源代码构建了 9.5.5)。新版本是 9.5.6。我没有从源代码构建 9.5.5 来测试任何这些;我当时使用的是当前版本,即 9.5.4。我现在已经在我的主机上更新到 9.5.6,并且 9.5.4 和 9.5.6 对于 OP 询问的表达式具有相同的行为。第一个 OP 表达式是(cond #t (else 2))
,OP 发现它的计算结果是#t
。Chez 在这种情况下不应返回,#t
但需要引发语法错误,如我上面的回答中所述。9.5.5 的维护者提出了一个问题,但该问题无法重现。第二个表达是(cond (> 2 1) (else 2))
; 这个表达式被 9.5.4、OP 的 9.5.5 正确处理,现在也被当前的 9.5.6 版本处理。