下面是我的代码,它将列表(carVal)
的汽车元素和列表(初始化为空)作为参数。我想将元素追加到列表中,但同样不起作用。在方案中添加元素列表
(define populateValues
(lambda (carVal currVal)
(append currVal(list carVal))
(display currVal)))
显示屏始终显示空列表()
。任何人都可以帮我理解为什么?
下面是我的代码,它将列表(carVal)
的汽车元素和列表(初始化为空)作为参数。我想将元素追加到列表中,但同样不起作用。在方案中添加元素列表
(define populateValues
(lambda (carVal currVal)
(append currVal(list carVal))
(display currVal)))
显示屏始终显示空列表()
。任何人都可以帮我理解为什么?
嗯,有append!
作为一种原始的,它解决了大部分的问题,如前所述,方案往往皱眉在突变时,这是可能的,但通常可以避免,因此所有突变的程序在其末尾都有一个!
(称为爆炸)。
另外,set!
不改变数据,它改变了环境,它使得一个变量指向另一个东西,原始数据保持不变。
Scheme中的突变数据非常麻烦,但是,为了让我自己实现append!看看它是如何做:
(define (append! lst . lsts)
(if (not (null? lsts))
(if (null? (cdr lst))
(begin
(set-cdr! lst (car lsts))
(apply append! (car lsts) (cdr lsts)))
(apply append! (cdr lst) lsts))))
注意使用set-cdr!
,这是一个真正的突变,它仅适用于对,它在内存中的数据发生突变,不像'设置“!。如果一对被传递给一个函数并且使用set-cdr进行了变异!或set-car!,它会在程序中的每一处发生变异。
这服从SRFI追加!规范说,它应该是可变的,它应该返回一个未定义的值,例如。
(define l1 (list 1 2 3 4))
(define l2 (list 2 3 4))
(define l3 (list 3 1))
(append! l1 l2 l3)
l1
l2
l3
该款显示器:
(1 2 3 4 2 3 4 3 1)
(2 3 4 3 1)
(3 1)
中可见,追加!可以采取无数的论点,它会改变他们,但最后。
虽然计划可能不是您理想的语言。使用追加!如前所述是非标准的,相反,append是首选的,它不会变异并被调用它的返回值。这是我实现这样:
(define (append . lsts)
(cond
((null? lsts) '())
((null? (car lsts)) (apply append (cdr lsts)))
(else (cons (caar lsts) (apply append (cdar lsts) (cdr lsts))))))
> (append (list 1 2 3) (list 4 5 6) (list 'granny 'porn))
(1 2 3 4 5 6 granny porn)
这都说明在没有突变,大量使用递归 的和没有用测序更熟悉方案的风格。
编辑:如果你只是想一些元素添加到列表中,而不是本身连接两个虽然:
(define (extend l . xs)
(if (null? l)
xs
(cons (car l) (apply extend (cdr l) xs))))
(define (extend! l . xs)
(if (null? (cdr l))
(set-cdr! l xs)
(apply extend! (cdr l) xs)))
(extend '(0 1 2 3) 4 5 6)
(define list1 '(0 1 2 3))
(extend! list1 4 5 6)
list1
哪个做你所期望的
(append foo bar)
返回级联foo
和bar
。它不会更改foo
或bar
。
您必须用set!更新currVal的值。你的榜样应该有
(set! currVal (append currVal (list carVal))
(display currVal)
请注意,这将改变函数内的'currVal',但在外面没有可见的效果。 – 2010-07-03 21:13:27
append
创建一个新名单,它不修改现有的一个。set!
- 但即使这样也会让你失望,因为它只会修改本地绑定。我需要拿出这个功能。你会在这种情况下建议什么? – 2010-07-03 20:54:30
你可以使用'box',这是一种指向(可变)值的指针。 **但是**我怀疑你确实需要这个功能 - 新手们通常认为他们必须这样做,因为他们习惯于突变是做事情的唯一方式。 – 2010-07-03 20:58:11
你真的需要想想什么确切的功能你正在寻找
如果你想改变引用列表的地方,那么你必须做相当于追加! (如其他答案中所述)。但是这很危险,因为你可能有其他的代码是不可改变的,如果你打算这么做的话,你的程序需要有一个!最终标志着这种危险。
一个廉价的逼近,你想要做什么,更实用的风格,就是:
(define (populateValues carVal currVal)
(let ((ll (append currVal (list carVal))))
(display ll)
ll))
注意,它使一个新的列表,不追加,显示结果,并返回新名单作为一种价值。如果您无法访问中间值,则这是一种有用的调试技术:绑定到变量,显示或记录它,然后返回它。
谢谢你的答案..顺便说一句......'奶奶','色情'..你可能想改变他们..否则你可能会被投票:) – 2010-07-16 04:40:49
@ darkie15它不会使答案不那么'有用'或'明确',如果人们因为这些事情想要降低它的话,那么这个网站已经失去了。此外,无论如何,你已经得到了答案。 =) 此外,其他人可以编辑它,如果他们想。 – Zorf 2010-07-16 19:18:09