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

时间:2017-09-28 15:32:56

标签: lisp common-lisp

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

具体来说,如果我要跑:

duration = c("1 h 10 min", "120 min")
sapply(strsplit(duration, " "), function(x){
    temp = as.numeric(x)
    if (length(temp) == 4){
        sum(as.numeric(temp[c(1, 3)]) * c(60, 1))
    }else{
        as.numeric(temp[1])
    }
    })
#[1]  70 120
#Warning messages:
#1: In FUN(X[[i]], ...) : NAs introduced by coercion
#2: In FUN(X[[i]], ...) : NAs introduced by coercion

输出为:(1 3)

该计划如下:

(findall 'numberp '(1 a 3))

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

我不明白的是,对“list(x)”的一系列连续调用最终将如何返回原子列表,例如(1 2)。

1 个答案:

答案 0 :(得分:6)

不确定为什么要标记你的问题SLIME,这是一个IDE。

让我们对您的代码进行格式化和缩进。

(defun findAll (fct l)
  (cond
   ((null l) nil)
   ((mapcan (lambda (x)
              (if (funcall fct x)
                  (list x)
                nil))
            l))))

可以这样写,但通常我们有一个T条件,以明确始终调用最后一个子句。

(defun findAll (fct l)
  (cond
   ((null l) nil)
   (t (mapcan (lambda (x)
                (if (funcall fct x)
                    (list x)
                  nil))
              l))))

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

(defun find-all (fn list)
  (mapcan (lambda (item)
            (if (funcall fn item)
                (list item)
              nil))
          list))
  

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

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