为什么这个程序返回一个原子列表?

edo*_*eld 0 lisp common-lisp

所以我在学校学习Lisp,我必须创建的程序之一就是使用mapcan复制remove-if-not的功能.我已经创建了程序,它工作正常,但我不明白输出.

具体来说,如果我要跑:

(findall 'numberp '(1 a 3))
Run Code Online (Sandbox Code Playgroud)

输出为:(1 3)

该计划如下:

(defun findAll (fct l)
(cond
        ((null l) nil)
        ((mapcan (lambda(x) (if (funcall fct x) (list x) nil )) l))
    )
)
Run Code Online (Sandbox Code Playgroud)

我对解决方案的理解如下:"对于列表中的每个元素,我调用lambda函数.如果函数的结果适合并且元素x返回true,则返回括号括起的元素,否则返回nil"

具体我不明白的是,对"list(x)"的一系列连续调用最终将如何返回原子列表,如(1 2).

Rai*_*wig 6

不确定为什么你已经标记了你的问题SLIME,这是一个IDE.

让我们格式化并缩进您的代码可读性.

(defun findAll (fct l)
  (cond
   ((null l) nil)
   ((mapcan (lambda (x)
              (if (funcall fct x)
                  (list x)
                nil))
            l))))
Run Code Online (Sandbox Code Playgroud)

有可能以这种方式编写它,但通常我们有一个T条件来说明总是调用最后一个子句.

(defun findAll (fct l)
  (cond
   ((null l) nil)
   (t (mapcan (lambda (x)
                (if (funcall fct x)
                    (list x)
                  nil))
              l))))
Run Code Online (Sandbox Code Playgroud)

由于MAPCAN已经处理空列表,您可以删除第一个COND和第一个子句.findAll通常命名为find-all.

(defun find-all (fn list)
  (mapcan (lambda (item)
            (if (funcall fn item)
                (list item)
              nil))
          list))
Run Code Online (Sandbox Code Playgroud)

对于列表的每个元素,我调用lambda函数.如果函数的结果适合并且元素x返回true,则返回括号括起的元素,否则返回nil

对于列表的每个元素,LIST调用lambda函数.如果函数FN和元素的结果ITEM返回true,则返回一个刚才的列表ITEM,否则返回空列表.最终结果是lambda函数的所有结果列表的(破坏性地)附加列表.