为什么“和”和“或”不在Scheme中?

时间:2012-12-30 05:36:54

标签: scheme boolean racket

我正在使用map来测试值列表,以查看它们是否具有给定属性。然后,我想看看他们是否都拥有该属性并返回true iff他们都这样做。

所以我的第一个想法是将列表and作为(and (list #t #t #f)),但这似乎将整个(#t #t #f)视为布尔值true并返回它。

所以,我想我可以使用foldl。我知道(foldl + 0 (list 1 2 3))有效,我认为(foldl and #t (list #t #t #f))也应该有效......但事实并非如此。

DrRacket中(使用#lang racket),我收到错误“and: bad syntax in: and”,这不是太有用,而是Repl.it(使用BiWaScheme })我收到错误“Error: #<Syntax and> is not a function”。

所以,我猜测and是一个宏?支持这一点似乎我只是评估+我得到#<procedure:+>,但对于and我得到and: bad syntax in: and(扼杀,xor是一个程序但{{1} }},ornor不是)。

那么,它是一个宏还是什么(可能是为了促进短路)?如果是这样,将执行“和”操作的布尔函数是什么?

3 个答案:

答案 0 :(得分:7)

其他答案已经解释了如何使用and“好像”它是一个函数,但and是一个宏的原因是支持你习惯的“短路”行为来自其他语言。例如,(and #f (display "blah"))不会打印任何内容,因为and会在看到错误值时立即停止。如果and是一个函数,则在调用它之前必须对它的两个参数进行求值,然后display无论如何都会发生。

答案 1 :(得分:6)

是的,and是一个宏。但你可以用

把它变成功能
(lambda (x y) (and x y))

,如

(foldl (lambda (x y) (and x y)) #t your-list)

答案 2 :(得分:1)

其他答案已经解释了为什么and不是直接的函数,但是语言设计的根本原因还有待揭示。

有核心原因:

  1. 方案提供的功能为proceduresA call of procedure要求使用applicative order个操作数(未指定操作数之间的评估顺序除外),这是strict evaluation的一种情况,其中要求在调用中评估所有操作数。
  2. and expression in Scheme需要支持对操作数进行“短路”评估(“在第一个评估结果为假值的表达式之后”“未评估任何剩余表达式”),例如{{3} },并非所有操作数都必须在调用中求值。

这些使用过程和支持短路评估的要求在逻辑上是不一致的,因此您不能在语言中将它们共存。宏可以支持非严格评估non-strict evaluation,因此就在这里。

但是,以上限制是由于Scheme的设计选择造成的。功能和非严格评估的概念本质上并不冲突。使用提供支持非严格评估的“功能”(Scheme的过程除外)的语言,可以实际实现类似的构造。值得注意的是,by expansion作为类Scheme的派生,既提供了应用组合器(如Scheme的过程),又提供了可操作的组合器(宏的替换,但是一流的过程,例如,允许作为操作数传递给另一个组合器) ,可以统称为“功能”。该语言的标准派生(非基本组合器)包括 both $and?(作为Scheme的and宏,具有短路评估功能)和and?(保证操作数总是先被评估的应用程序,就像普通的严格评估函数一样)。作为实现,Klisp提供了$and?的派生作为the Kernel language中的区别示例。