2014-12-04 30 views
0

我想將原子添加到列表的末尾,並且還希望原始列表發生更改。我已經寫了這個小程序,但它不會改變列表。爲什麼是這樣的,我該如何改變它。 PS:我是新來的計劃。將原子添加到方案中的列表中

(define (append! l1 l2)  
    (set! l1 (append l1 (list l2))) 
) 

回答

0

只需使用句法擴展:

(define-syntax-rule (append! l1 at) 
    (set! l1 (append l1 (list at)))) 

然後

> (define l1 '(1 2 3)) 
> (append! l1 4) 
> l1 
'(1 2 3 4) 
1

與您的實現問題是,你只是改變一個函數的參數,但功能退出後功能列表「外部」保持不變。我們可以修改就地使用set-car!set-cdr!列表中,但它是一個有點棘手,因爲首先我們要找到合適的cons細胞進行修改,並返回列表的頭:

(define (append! lst atom) 
    (let ((head lst)) 
    (let loop ((lst lst)) 
     (cond ((null? lst) (list atom)) 
      ((null? (cdr lst)) 
      (set-cdr! lst (list atom)) 
      head) 
      (else (loop (cdr lst))))))) 

(define l1 '(1 2 3 4)) 
l1 
=> '(1 2 3 4) 

(append! l1 5) 
l1 
=> '(1 2 3 4 5) 

甚至更​​好,我們可以忘掉到位變異名單和接受功能的編程風格,這是推薦的方式使用計劃時:

(define l1 '(1 2 3 4)) 

(define (append-tail lst atom)  
    (append lst (list atom))) 

(define l2 (append-tail l1 5)) 

l1 
=> '(1 2 3 4) 
l2 
=> '(1 2 3 4 5) 
+0

那麼問題是,我想在另一個使用這個功能,所以這並沒有多大幫助。 – pesho 2014-12-04 21:04:18

+0

@pesho我更新了我的答案,其中更接近於你想要的東西,但請相信我:在Scheme中,這不是正確的做事方式,建議不要改變列表的版本 - 正如你所說,你只是在學習Scheme,所以如果你開始以正確的方式做事,會更好。 – 2014-12-04 21:23:57

0

set!是變異的結合,但沒有價值,有set-car!set-cdr!變異值,如果是一對。

set!作爲改變任務。因此,如果您有xy都是值"value"並使用set!x更改爲"anothervalue"。如果您有一個過程併爲其中一個參數指定了不同的值,您將重新定義本地名稱,而不會更改傳遞給該過程的變量。

set-car!set-cdr成對工作。因此,它們會改變數值並與變量無關。

如:

(define x (list 1 2 3)) ; x is (1 2 3) 
(define y x)    ; y is (1 2 3) 
(define z y)    ; z is (1 2 3) 

;; changing the binding of z 
(set! z (append x '(1))) ; z is (1 2 3 1) while x and y still are (1 2 3) 

;; changing the value of x 
(set-car! x 2)    ; both x and y are now (2 2 3) 

考慮到這一點,你可以改變一個變量,但請記住,這非常變量可以有與其他變量共享結構,因此你可能會比你最初雖然使用set-cdr!改變更多變數

#!r6rs 
(import (rnrs) 
     (rnrs mutable-pairs)) 

(define (append-elt! lst value) 
    (when (null? lst) 
    (assertion-violation 'append! "lst cannot be null" lst)) 

    (let loop ((lst lst)) 
    (if (null? (cdr lst)) 
     (set-cdr! lst (list value)) 
     (loop (cdr lst))))) 

(define q (append y y)) ; We make a copy of y with y as shared tail 
(append-elt! q 'a)  ; we change the last pair of q which also is the last pair of y and z 
q ; ==> (1 2 3 1 2 3 a) 
x ; ==> (1 2 3 a) 
z ; ==> (1 2 3 a)