List Common Lisp-平铺可能包含符号的列表
这是#7 of:转换一个列表,可能将列表作为元素保存到一个“平面”列表中,方法是(递归地)将每个列表替换为其元素。我尝试过几种解决方案,例如从#或。它们都可以工作,但如果我要展平包含引用元素的列表,就会遇到问题。例如:List Common Lisp-平铺可能包含符号的列表,list,common-lisp,quote,flatten,List,Common Lisp,Quote,Flatten,这是#7 of:转换一个列表,可能将列表作为元素保存到一个“平面”列表中,方法是(递归地)将每个列表替换为其元素。我尝试过几种解决方案,例如从#或。它们都可以工作,但如果我要展平包含引用元素的列表,就会遇到问题。例如: > '(a 'b c) (A 'B C) > '(a (quote b) c) (A 'B C) > (flatten '(a 'b c)) (A QUOTE B C) 在后一种情况下,我希望得到: (A 'B C) “的内部表示似乎妨碍了这项任务!SB
> '(a 'b c)
(A 'B C)
> '(a (quote b) c)
(A 'B C)
> (flatten '(a 'b c))
(A QUOTE B C)
在后一种情况下,我希望得到:
(A 'B C)
“的内部表示似乎妨碍了这项任务!SBCL、CLISP、ECL。。。它们的行为都是一样的。列表中引用的元素?这通常是没有意义的。你为什么要引用它
(a b c)
是三个符号的列表。为什么要引用列表中的元素?类似于(a'b c)
?为什么?报价的目的是什么
在常见的Lisp中,是一个readmacro,它将'a
扩展为(引号a)
。由于这是一个普通列表,典型的展平操作会将符号QUOTE
和a
收集到展平列表中。这是因为扁平函数调用检查某个对象是否是原子。如果您不希望这样做,那么展平函数需要检查某个元素是原子还是以QUOTE
作为第一个符号的两元素列表
但正如我上面所说的,默认用法只是将符号展平,因为引用的符号在列表中通常没有用处。否则,需要扩展展平函数
例如:
(defun flatten (l &key (test #'atom))
(cond ((null l) nil)
((funcall test l) (list l))
(t (loop for a in l nconc (flatten a :test test)))))
CL-USER > (flatten '(a (('b) c) ('d) )
:test (lambda (item)
(or (atom item)
(and (eq (first item) 'quote)
(null (cddr item))))))
(A (QUOTE B) C (QUOTE D))
您遇到的问题是由于LISP读取表达式时引号符号(')转换为(引号…)。为了便于读取输出,LISP打印列表时会进行相应的转换。因此,当让LISP将其作为列表读取时,无法区分两者。
(defun flatten(l)(cond((null l)nil)((atom l)(list l))((equal l(list'QUOTE(second l)))(cdr l))(t(在l中为a加上一个循环(flatten a‘))
这给了我(ab C)
。我想如果我有(flatten'(A'B C))
我就无法获得(A'B C)
传递给flatten的列表没有控制权。我认为这解决了我的问题,尽管有一点不对称:)@Antonio Bonifati:参见添加的示例