我编写了将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
。
答案 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>