2016-04-07 39 views
1

我有一個關於在不使用set的情況下在內存中保留列表的問題!不使用設置更新列表! - Scheme

我有限定的初始空列表,

(define database (list)) 

然後我有這個過程,它檢查該密碼是正確的,並增加了所述一對到列表中。

(define (set-pass l) 
    (if (pair? l) 
    (if (check-pass (second (last l))) 
     (add-to-list l) 
     "password does not meet policy requirements" 
    ) 
    "invalid input" 
) 
) 

和一個附加到列表的過程:

(define (add-to-list l) 
    ;(append database l) 
    ;implement this. 
) 

問題是,我必須多次調用這個過程:

(set-pass '('john '(X p c F z C b Y h 1 2 3 4 : :))) 
(set-pass '('john '(X p c F z C b Y : 1 2 3 4 : :))) 
(set-pass '('john '(X p c F z C b : : 1 2 3 4 : :))) 

我實現的過程添加-TO-列表就像我打電話set-pass一次(如上所示附加),但如果我多次調用它,我找不到實現的方法。我試過幾個東西here,herehere。但我無法達到我想要的。那我該怎麼做?

+0

即使我們將列表封裝在過程中,在某些時候我們不得不使用'set!'來重新分配它。要麼,要麼繼續將修改後的列表作爲參數傳遞給需要它的函數。 –

回答

1

有可能通過具有數據庫作爲變量功能上做到這一點:

(let loop ((input (read-line)) (database '())) 
    (display (format "inserting ~a\n" input)) 
    (loop (read-line) 
     (cons input database))) 

的其他功能(刪除等)的工作方式相同,你與根據操作改變的結構發生。

您還可以使用set-cdr!更新列表。儘管set!突變了符號指向的內容,set-cdr!突變了一對的cdr。因爲它需要一個對你需要有第一個元素是一些虛擬的數據:

(define database (list "head")) 

(define (add element) 
    (let ((tmp (cdr database))) 
    (set-cdr! database (cons element tmp)))) 

(define (delete element) 
    (let loop ((prev database) (cur (cdr database))) 
    (cond ((null? cur) #f) 
      ((equal? (car cur) element) 
      (set-cdr! prev (cdr cur))) 
      (else (loop cur (cdr cur)))))) 

(define (get) 
    (cdr database)) 

(add 1) 
(add 2) 
(add 3) 
(get) ; ==> (3 2 1) 
(delete 2) 
(get) ; ==> (3 1) 

第二你允許突變的貓是在袋子外面和所有突變是可用的。例如。如果提供了set!,則可以使用閉包創建可變對象,並且如果提供了set-car!/set-cdr!,則可以獲得與框的可變綁定。