scheme - 为什么本次迭代这里会产生空列表?
问题描述
让我们使用以下函数来获取一对数字:
; (range 1 3) --> '(1 2 3)
(define (range a b)
(if (> a b) nil
(cons a (range (+ 1 a) b))))
; generate pair of two numbers with 1 <= i < j <= N
(define (get-pairs n)
(map (lambda (i)
(map (lambda (j) (list i j))
(range 1 (- i 1))))
(range 1 n)))
(get-pairs 2)
; (() ((2 1)))
(get-pairs 3)
(() ((2 1)) ((3 1) (3 2)))
为什么上面会产生'()
作为输出的第一个元素?将此与 python 进行比较,我希望它只给出三对,例如:
>>> for i in range(1,3+1): # +1 because the range is n-1 in python
... for j in range(1,i-1+1):
... print (i,j)
...
(2, 1)
(3, 1)
(3, 2)
我想也许它与什么时候i
是1有关?
(map (lambda (j) (list 1 j)) '())
; ()
这只是Scheme中的一个标识,带有空列表的地图总是一个空列表吗?
解决方案
当i
为 1 时,内图结束(range 1 0)
,这是()
你自己定义的。由于map
需要一个过程和一个(或多个)值列表,依次将该过程应用于列表中的每个值,并返回一个包含结果的列表,因此将任何过程映射到一个不包含值的列表将返回一个不包含值的列表.
它可能有助于创建一个简单的定义,map
以了解它是如何工作的。请注意,此定义并不完整;它只需要一个列表参数:
(define (my-map proc xs)
(if (null? xs)
'()
(cons (proc (car xs))
(my-map proc (cdr xs)))))
这里,当输入列表为空时,没有要映射的值,因此返回一个空列表。否则,该过程proc
将应用于输入列表中的第一个值,并将结果转换为映射到列表其余部分的结果。
几点观察:
首先,空列表nil
在标准 Scheme 或 vanilla Racket 中都没有表示,您不应该使用它。在早期,Schemenil
被允许作为来自其他 lisps 的程序员的拐杖,但很长一段时间没有这种情况。我认为它从未出现在任何 RnRS 标准中,但nil
可能在某些特定实现中仍然存在,直到 R4RS(1991 年)。SICP就是那个时代的。今天,您应该使用'()
来表示 Scheme 中的空列表文字,以便您的代码可以在任何 Scheme 实现上运行。Racket#lang sicp
允许直接运行书中的代码,但这不应该阻止您使用通用符号。请注意,Common Lisp确实使用nil
作为一个自评估符号来表示空列表和布尔值 false。在 Scheme 中看到这一点,今天看起来不正确。
其次,当你试图理解 Scheme 代码时,如果用 Python 来思考,你可能会更容易误入歧途。在这种特殊情况下,map
是一个迭代构造,但它与for
循环不同。循环通常for
用于副作用,但map
用于转换列表。Scheme 有一种for-each
形式,旨在用于其副作用,从这个意义上说,它更像是一个for
循环。不过,上面发布的 Python 版本与 Scheme 版本完全不同。不是在列表中返回结果,而是打印结果。在 Scheme 代码中,当i
为 1 时,内部映射结束(range 1 0)
--> ()
。但是,在 Python 代码中,当i
为 1,内部循环结束range(1, 1)
,因此该for
循环的主体不执行,也不打印任何内容。
最好仔细考虑你想理解的 Scheme 代码,回到基本定义上,而不是拼凑一个基于 Python 的模型,其中可能有未考虑的极端情况。
推荐阅读
- spring - 使用 @RequestBody 时设置默认的内容类型标头
- php - 已加载时未找到 PHP 类
- r - 根据先前的值命名列中的值,没有系统顺序
- php - WebSocket 握手期间出错:意外的响应代码:200 - Laravel Websockets
- coffeescript - Webdriver.io。使用 CTRL+单击 coffescript 突出显示多个元素
- uml - 如何在 UML 中的类构造函数中为新类建模
- javascript - 有没有比 JSON 更简单的语法允许结构化文本,并且可以在 javascript 中处理?
- amazon-web-services - AWS CodeDeploy 可以为 lambda 进行跨账户部署吗?
- ios - 当应用程序未在 Swift 中运行时接收数据
- java - 如何外部化配置服务器(而不是客户端)的 application.yml?