下面是我的代碼,它將列表(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