Iva*_*lev 4 lisp scheme list cons racket
简单代码:
> (cons null (cons 1 2))
'(() 1 . 2)
> (cons (cons 1 2) null)
'((1 . 2))
Run Code Online (Sandbox Code Playgroud)
最初,我希望结果是一样的。我能想到一些含糊的解释,但也想听听知识渊博的人的强项。
为什么结果不一样?
用数学的话说,有些运算是可交换的。加法是可交换的,因此(+ 1 2)和(+ 2 1)两者具有相同的结果。除法不是可交换的;(/ 1 2)并且(/ 2 1)没有相同的结果。
OP 期望(cons null (cons 1 2))和(cons null (cons 1 2))应该具有相同的结果实际上cons是一个交换过程的期望。它不是。如果cons 是可交换的,则(cons 1 2)and(cons 2 1)将是等价的。但:
> (cons 1 2)
(1 . 2)
> (cons 2 1)
(2 . 1)
Run Code Online (Sandbox Code Playgroud)
该cons过程创建了一个cons单元格,该单元格具有两个传统上称为 thecar和 the 的组件cdr;它cons从两个参数创建单元格。第一个参数放在car单元格的 中,第二个参数放在cdr单元格的 中。其中(cons 1 2),1 放在 中car,2 放在 中cdr;但是用(cons 2 1)2 放在 中car,而 1 放在cdr. 你可以看到,(cons 1 2)并且(cons 2 1)必然是不同的,因为car与cdr在的cons细胞是不同的。
OP例如(cons null (cons 1 2))放置在空表car一的cons细胞,并把细胞(1 . 2)(自身创造了另一个呼叫cons),在cdr该小区的。这是虚线列表(如下所述)(() . (1 . 2));这样的点列表通常在 REPL 中表示为(() 1 . 2)。
但随着(cons (cons 1 2) null)细胞(1 . 2)代替放置在car一个的cons细胞,随着空单的地方cdr该小区的:((1 . 2) . ())。
现在,在 Lisps 中,列表是一串以cons空列表结尾的单元格。链状(1 . (2 . 3))有时称为点列表或不正确的列表;这是一个cons不以空列表终止的单元格链。在 REPL 中,您经常会看到(1 . (2 . 3))表示为(1 2 . 3). 另一方面,一个类似链的链(1 . (2 . ()))被称为一个适当的链表;这是一个连锁cons的细胞并与空列表终止。您会在 REPL 中看到这表示为(1 2). 通常当有人使用非限定词列表时,他们的意思是正确的列表。
所以,OP代码((1 . 2) . ())等价于适当的列表((1 . 2)),其中包含单个成员(1 . 2),这肯定与点列表不同(() 1 . 2)。
还有另一个程序 ,append它的行为符合 OP 的预期。双方(append null (append '(1) '(2)))并(append (append '(1) '(2)) null)评价到'(1 2)。最后两个表达式的计算结果是一样的,因为空列表标识元素的操作append。也就是说,将非空项目列表与空列表连接会返回非空列表的副本。类似地,将空列表与非空列表连接会返回非空列表的副本。但append不是可交换的;append返回一个列表,其中包含第一个列表的元素,后跟第二个列表的元素。所以,(append '(1 2) '(3 4))--> '(1 2 3 4),但是(append '(3 4) '(1 2))--> '(3 4 1 2)。
还有另一个相关的数学属性:关联性。另外是关联的,即(+ 1 (+ 2 3))与(+ (+ 1 2) 3)两个评价相同的结果。使用中缀表示法,1 + (2 + 3)并且(1 + 2) + 3两者都评估为相同的结果。这有一个有趣的后果。由于分组并不重要,因此将上述中缀表达式简单地写为1 + 2 + 3. 对应的前缀表达式是(+ 1 2 3),并且 Lisps 确实支持这种表示多个操作数的加法的方式。
cons是不是联想。由于cons从它的参数创建了一个pair,它不能是关联的。随着(cons 1 2)对(1 . 2)被创建。与(cons 1 (cons 2 3))所述一对(2 . 3)被放置在cdr另一对,结果是(1 . (2 . 3))(在REPL为大概表示(1 2 . 3))。但是随着(cons (cons 1 2) 3)对(1 . 2)被创建并放置在car另一对的 中,导致((1 . 2) . 3). 请注意,由于cons不是关联的,因此表达 like(cons 1 2 3)没有意义;行动的分组尚不清楚。
但是append 是联想的。随着(append '(1) '(2))列表(1 2)的创建。随着(append '(1) (append '(2) '(3)))名单(2 3)的创建,列表中(1),然后用结合(2 3),从而导致(1 2 3)。用(append (append '(1) '(2)) '(3))列表(1 2)创建然后与列表连接(3),也产生列表(1 2 3)。由于分组在这里并不重要,因此简单地编写 是有意义的(append '(1) '(2) '(3)),并且与加法一样,Lisps 确实支持这种表达追加操作的方式。
| 归档时间: |
|
| 查看次数: |
147 次 |
| 最近记录: |