将函数作为参数传递 - lambda表达式错误?

LuX*_*orX 1 lisp functional-programming function common-lisp parameter-passing

我正在尝试创建一个接受列表和函数作为参数的函数,并将该函数应用于List中的每个元素.这是我的尝试:

(defun filter(fn L)
  (if (eq 0 (length L))
      (print "list empty")
      (print (mapcar (lambda (n) (#'fn n)) L))))
(print (filter #'evenp '(1 2 2 3 4)))
Run Code Online (Sandbox Code Playgroud)

这是第二次尝试:

(defvar R nil)
(defun filter(fn L)
  (if (eq 0 (length L))
      nil
      (cons (R (funcall fn (car L)) filter(fn (cdr L))))))
(print(filter #'evenp '(1 2 2 3 4)))
Run Code Online (Sandbox Code Playgroud)

但对于一些简单的混乱和无法解释的原因,我得到第一个错误:

#'FN should be lambda expression.
Run Code Online (Sandbox Code Playgroud)

这是第二个:

Undefined function R
Run Code Online (Sandbox Code Playgroud)

我尝试了很多东西但到目前为止还没有任何工作.

编辑::感谢您的帮助到目前为止.这个:

(defun filter(fn L)
  (if (eq 0 (length L))
      (print "list empty")
      (remove-if-not #'fn '(1 2 3 4 5))))

(print (filter #'evenp '(1 2 2 3 4)))
Run Code Online (Sandbox Code Playgroud)

这应该做到这一点.但我仍然得到了

Undefined function FN
Run Code Online (Sandbox Code Playgroud)

错误.该怎么办???

sds*_*sds 10

怎么做你想要的

filterremove-if-not 在Common Lisp中调用:

(remove-if-not #'evenp '(1 2 3 4 5))
==> (2 4)
Run Code Online (Sandbox Code Playgroud)

您的代码有什么问题 - 语法上

第一次尝试

当您尝试调用存储在变量中的函数(或作为参数传递给函数)时,您需要使用funcallapply:

(mapcar (lambda (n) (funcall #'fn n)) L)
Run Code Online (Sandbox Code Playgroud)

或者只是传递给mapcar:

(mapcar fn L)
Run Code Online (Sandbox Code Playgroud)

第二次尝试

这是一团糟.你需要学习Common Lisp语法,有很多好书(参见 想要学习常见的lisp).

具体问题是R在函数位置(第一个列表元素)但它没有被定义为函数 - 它是一个变量.即使您解决了这个问题,也存在更多问题.你应该读一本书,然后自己解决,这将是一个有用的练习.

基本上,在Common Lisp中,括号是有意义的.例如,在C你可以写x+y,(x+y),(x)+(y)&C和它们的意义是相同的.在Common Lisp R(R),((R))&c是非常不同的.

第三次尝试("编辑")

(defun filter(fn L)
  (if (eq 0 (length L))
      (print "list empty")
      (remove-if-not #'fn '(1 2 3 4 5))))
Run Code Online (Sandbox Code Playgroud)

这里有一个变量 fn,但是你正在使用它,就好像它是一个函数(#'fn).

你需要这样做

      (remove-if-not fn '(1 2 3 4 5))
Run Code Online (Sandbox Code Playgroud)

代替.

您的代码有什么问题 - 语义上

没必要 print

首先,print几乎 从来不是在代码中使用的正确功能.使用princ,prin1write改为.

其次,Common Lisp REPL 代表Read-Eval- Print Loop,因此您不需要显式打印函数的返回值.

遵循编码约定

您为其他人(包括您自己6个月后)编写代码以便阅读,而不仅仅是计算机运行.如果遵循约定,包括命名变量和函数,括号放置,缩进和c,则可以使代码更具可读性.

与0比较使用 zerop

(zerop X)而不是(eq 0 X)(实际上,你应该使用eql数字,但现在变得太毛茸茸了).

length 可能很贵

如果您需要知道的是否为空,请不要扫描整个列表.IOW,

(if (zero (length l))
    (print "the list is empty")
    (mapcar ... l))
Run Code Online (Sandbox Code Playgroud)

写得更好

(if (null l)
    (print "the list is empty")
    (mapcar ... l))
Run Code Online (Sandbox Code Playgroud)