在 lisp 中如何使用函数作为变量?

发布于 2024-11-27 08:27:19 字数 426 浏览 1 评论 0原文

我正在尝试编写一个函数来检查列表 x 中的每个元素是否都具有属性 a,所以我写道:

(defun check (a x)
  (if (listp x)
    (eval (cons 'and (mapcar #'a x)))))

但它不起作用。 (基本上我希望 a 是函数的名称,例如 blablabla,并在检查函数的主体中,由 #'a 我想指的是函数 blablabla,而不是名为 a 的函数。)现在上面的代码不起作用。我认为在 Lisp 中应该能够插入函数。我该如何修复它?

(这实际上是我第一天使用 lisp,所以这可能是一个愚蠢的问题;) 顺便说一句,我正在使用 Lispworks 6.0 个人版本。)

I'm trying to write a function which checks if every element in the list x has property a, so I wrote:

(defun check (a x)
  (if (listp x)
    (eval (cons 'and (mapcar #'a x)))))

but it doesn't work. (Basically I want a to be the name of a function, say blablabla, and in the body of the check-function, by #'a I want to mean the function blablabla, instead of a function called a.) Now the code above doesn't work. I think in Lisp one should be able to plug in functions. How can I fix it?

(It is literally my first day on lisp, so it might be a stupid question ;)
and BTW I'm using Lispworks 6.0 personal version.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

若水般的淡然安静女子 2024-12-04 08:27:19

这里不需要使用尖引号语法。其目的是在变量位置使用函数名称,但 a 已经是一个变量。只需编写 a 而不是 #'a

There is no need to use the sharp-quote syntax here. Its purpose is to use a function name in a variable position, but a is a variable already. Just write a instead of #'a.

萌酱 2024-12-04 08:27:19

您不需要eval,您可以使用apply
对于问题:您需要 funcall 因为您提供 a 作为参数。 (编辑:不是在这种情况下。)通过引用,您只是引用函数 a 而不是此函数中的 a。

(defun check (a xs)
  (if (listp xs)
      (every #'identity (mapcar a
                                xs))))

更好,使用loop

(defun check (a xs)
  (if (listp xs)
      (loop for x in xs
            always (funcall a x))))

最好,使用every

(defun check (a xs)
   (if (listp xs)
     (every a xs)))

You don't need eval you can use apply.
To the problem: You need funcall because you provide a as argument. (Edit: Not in this case.) By quoting you just refer to the function a not the a in this function.

(defun check (a xs)
  (if (listp xs)
      (every #'identity (mapcar a
                                xs))))

Better, use loop:

(defun check (a xs)
  (if (listp xs)
      (loop for x in xs
            always (funcall a x))))

Best, use every:

(defun check (a xs)
   (if (listp xs)
     (every a xs)))
暗喜 2024-12-04 08:27:19

这是我如何编写类似您的检查功能的内容。我尝试给它起一个更具描述性的名字。

(defun are-all-elements-fullfilling-fun-p (fun ls)
  (every #'identity (mapcar fun ls)))

编辑:请注意,一个更短、更好的定义是

(defun are-all-elements-fullfilling-fun-p (fun ls)
      (every fun ls)))

现在假设我们想用这个函数调用它。请注意,我倾向于尽可能使用声明。我经常搞砸一些事情,如果编译器能够找出错误,那么调试就很容易。而且代码运行速度会更快。

(defun is-even-p (n)
  (declare (type number n))
  (the boolean (= 0 (mod n 2))))

您必须在此处放置#':

(are-all-elements-fullfilling-fun-p #'is-even-p '(1 2 3 4))
(are-all-elements-fullfilling-fun-p #'is-even-p '(38 2 4))

Here is how I would write something like your check function. I tried to give it a more descriptive name.

(defun are-all-elements-fullfilling-fun-p (fun ls)
  (every #'identity (mapcar fun ls)))

Edit: Note that a shorter and better definition is

(defun are-all-elements-fullfilling-fun-p (fun ls)
      (every fun ls)))

Now let's say we want to call it with this function. Note that I tend to use declarations when possible. I quite often screw something up and debugging is easy if the compiler can figure the error out. Also the code will run faster.

(defun is-even-p (n)
  (declare (type number n))
  (the boolean (= 0 (mod n 2))))

You have to place the #' here:

(are-all-elements-fullfilling-fun-p #'is-even-p '(1 2 3 4))
(are-all-elements-fullfilling-fun-p #'is-even-p '(38 2 4))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文