3

map用来测试值列表以查看它们是否具有给定的属性。然后,我想看看他们是否都拥有该属性并返回如果他们都true 拥有

所以我的第一个想法是只给出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是一个宏?支持这一点,如果我只是评估+I get #<procedure:+>,但对于andI get and: bad syntax in: and(扼要地说,xor是一个过程但是or,nornand不是)。

那么,是宏还是什么(可能是为了方便短路)?如果是这样,将执行“与”操作的布尔函数是什么?

4

3 回答 3

8

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

于 2013-01-01T12:50:20.920 回答
6

是的,and是一个宏。但是你可以把它变成函数

(lambda (x y) (and x y))

如在

(foldl (lambda (x y) (and x y)) #t your-list)
于 2012-12-30T05:44:19.197 回答
1

其他答案已经解释了为什么and不是直接函数,但语言设计中的深层原因仍有待进一步揭示。

有核心原因:

  1. Scheme 提供函数作为过程过程调用需要操作数的应用顺序(除了未指定操作数之间的求值顺序),这是严格求值的情况,其中所有操作数都需要在调用中求值。
  2. andScheme 中的表达式需要支持操作数的“短路”求值(“任何剩余的表达式都不求值”在“第一个求值为假值的表达式”之后),即非严格求值的情况,其中并非所有操作数必须在调用中进行评估。

这些使用过程和支持短路评估的要求在逻辑上是不一致的,所以你不能让它们在语言中共存。宏可以通过扩展支持非严格评估,所以在这里。

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

于 2018-12-03T12:37:36.540 回答