【问题标题】:Updating a list without using set! - Scheme不使用 set 更新列表! - 方案
【发布时间】:2016-04-07 15:13:12
【问题描述】:

我在不使用 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),但如果我多次调用它,我找不到实现方法。我尝试了一些提到的hereherehere。但我无法实现我想要的。那么我该怎么做呢?

【问题讨论】:

  • 即使我们将列表封装在过程中,有时我们也必须使用set! 重新分配它。要么,要么继续将修改后的列表作为参数传递给需要它的函数。

标签: list scheme


【解决方案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!,则可以使用框获取可变绑定。

【讨论】:

    猜你喜欢
    • 2017-10-18
    • 1970-01-01
    • 2021-09-22
    • 2021-01-12
    • 2017-11-23
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2017-03-19
    相关资源
    最近更新 更多