Lisp关联列表错误

时间:2016-04-06 16:32:21

标签: lisp

我编写了将cons cell插入关联列表的代码。 例如,有关联列表

class SilentLogger
  def initialize
    @silencers = []
  end

  def add_silencer(&block)
    @silencers << block
  end

  def call(severity, timestamp, progname, msg)
    backtrace = (String === msg) ? "#{msg}\n" : "#{msg.inspect}\n"

    return backtrace if @silencers.empty?

    @silencers.each do |s|
      backtrace = backtrace.split("\n").delete_if { |line| s.call(line) }
    end

    backtrace.join("\n")
  end
end

我要插入cons小区((1 . a) (3 . c) (4 . d)) ,然后这个程序产生

(2 . b)

但是我的代码引发了异常

((1  a) (2 . b) (3 . c) (4 . d))

下面是我的代码

(car L) should be a lambda expression

(defun INSERTCELL (R L) (cond ((< (car L) (car R)) cons((car L) INSERTCELL(R (cdr L)))) (t cons(R L)))) R(2 . b)L,因此((1 . a) (3 . c) (4 . d))应插入R

2 个答案:

答案 0 :(得分:1)

SDS's answer负责处理代码中的印刷问题以及其他一些错误。也就是说,我认为值得注意的是,可能还有其他方法可以做到这一点。首先,不必按顺序存储关联列表。如果您不需要您的顺序,那么您只需使用acons将新元素添加到开头:

(let ((alist '((1 . a) (3 . c) (4 . d))))
  (acons 2 'b alist))
;=> ((2 . B) (1 . A) (3 . C) (4 . D))

如果确实需要维护排序条件,可以选择使用上面的方法,然后使用sort列表。但是,这可能有点矫枉过正,因为您已经知道关联列表已经排序,您只需将新元素放在其位置即可。为此,您可以使用内置的merge函数来合并关联列表和新元素(通过将其包装在列表中,因此它是一个元素的关联列表):

(let ((alist (copy-list '((1 . a) (3 . c) (4 . d))))
      (new (list (cons 2 'b))))
  (merge 'list alist new '< :key 'car))
;=> ((1 . A) (2 . B) (3 . C) (4 . D))

(let ((alist '((1 . a) (3 . c) (4 . d))))
  (merge 'list (copy-list alist) (copy-list '((2 . b)))
         '< :key 'car))
;=> ((1 . A) (2 . B) (3 . C) (4 . D))

请注意,合并具有破坏性(即允许修改其参数),这就是我在这里使用 copy-list 来获取新数据的原因。在您的情况下,由于您可能会逐步构建列表,因此保存结果可能 。例如,

(defun insert-cell (key value alist)
  (merge 'list alist (list (cons key value))
         '< :key 'car))
(let ((alist '()))
  (setf alist (insert-cell 1 'a alist))
  (setf alist (insert-cell 4 'd alist))
  (setf alist (insert-cell 3 'c alist))
  (setf alist (insert-cell 2 'b alist))
  alist)
;=> ((1 . A) (2 . B) (3 . C) (4 . D))

答案 1 :(得分:0)

Lisp中的函数调用是cons cells

(cons 1 2)
==> (1 . 2)

如果您修复了代码:

(defun insertcell (R L)
  (cond ((< (caar L) (car R)) (cons (car L) (insertcell R (cdr L))))
        (t (cons R L))))

它有效:

(insertcell '(2 . b) '((1 . a) (3 . c) (4 . d)))
==> ((1 . A) (2 . B) (3 . C) (4 . D))

请注意,您还需要执行(caar L),而不是(car L),因为L是一个列表,因此要访问第一个密钥,您需要拨打car两次。< / p>