2016-04-07 101 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!,则可以获得与框的可变绑定。