不使用 set 更新列表! - 方案
Updating a list without using set! - Scheme
关于在不使用 set 的情况下在内存中保留列表的问题!
我定义了一个初始空列表,
(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 : :)))
我实现了 add-to-list 过程,就像我调用一次 set-pass 一样(如上所示带有 append),但是如果我多次调用它,我找不到实现的方法。我尝试了提到的一些事情 here, here and here。但是我无法实现我想要的。那我该怎么做呢?
可以通过将数据库作为变量来在功能上做到这一点:
(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!
,你可以通过框获得可变绑定。
关于在不使用 set 的情况下在内存中保留列表的问题!
我定义了一个初始空列表,
(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 : :)))
我实现了 add-to-list 过程,就像我调用一次 set-pass 一样(如上所示带有 append),但是如果我多次调用它,我找不到实现的方法。我尝试了提到的一些事情 here, here and here。但是我无法实现我想要的。那我该怎么做呢?
可以通过将数据库作为变量来在功能上做到这一点:
(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!
,你可以通过框获得可变绑定。