带有剩余参数的函数调用带有剩余参数的函数

2024-06-18

假设我们有一个函数func1 :

(defun func1 (&rest values)
  ; (do something with values...)
  (loop for i in values collect i))

现在,我们有一个函数func2哪个调用func1 :

(defun func2 (&rest values)
  ; (do something with values...)
  (func1 ???))

我应该放什么来代替???“复制”所有参数func2's values to func1's values ?

例如,我会有以下行为:

(func2 1 2 3 4) ; result is (1 2 3 4) and not ((1 2 3 4)).

In 之前的一个问题 https://stackoverflow.com/q/52796579/9614866我尝试做这样的事情:

(defun func2 (&rest values)
  (macrolet ((my-macro (v)
               `(list ,@v)))
    (func1 (my-macro values))))

但defun无法获取该值,因为它不是运行时。在这个答案 https://stackoverflow.com/a/52796954/9614866,他建议我使用apply,但是这个函数需要一个&rest参数太,所以它不能解决我的问题......

如果可以的话我宁愿避免改变两个函数的原型和行为func1.


在 Common Lisp 中,它必须是

(apply #'func1 values) ;; since `func1` has to be looked up in function namespace

请记住,Clojure 和 Racket/Scheme 是 Lisp1,而 common lisp 是 Lisp2。

替代解决方案(只是为了方便)

我问自己,如何在没有apply-只是为了。 问题在于

`(func2 ,@values)

是,如果例如

 (func2 (list 1 2 3) (list 4) 5)

被称为,values变量是((1 2 3) (4) 5)但当它被拼接成(func1 ,@values),创建的是(func1 (1 2 3) (4) 5)。但如果我们将其与func2称呼, 应该是(func1 (list 1 2 3) (list 4) 5)这也许是不可能的,因为当(func2 (list 1 2 3) (list 4) 5)叫做 - 以 lisp 方式 - 的论点func2在进入函数体之前分别进行评估func2,所以我们最终得到values作为已评估参数的列表,即((1 2 3) (4) 5).

所以不知何故,关于论点func1在最后一个表达式中,我们是一步评估另类.

但有一个解决方案quote,我们在给出每个参数之前设法引用它func1在最后一个表达式中,“同步” the func1函数调用 - 让参数的计算暂停一轮。

所以我的首要目标是产生一个新的values列出里面的func2body,其中每个值列表的参数都被引用(这是在 let 绑定中完成的)。 然后在最后拼接这个quoted-values列出最后一个表达式:(func1 '(1 2 3) '(4) '5)可以看作等价于(func1 (list 1 2 3) (list 4) 5)对于此类问题/此类调用。 这是通过以下代码实现的:

(defun func2 (&rest vals)
  (let ((quoted-values (loop for x in vals
                                     collect `',x)))
    ; do sth with vals here - the func2 function -
    (eval `(func1 ,@quoted-values))))

这是一种宏(顺便说一句,它创建代码。它组织新代码),但在运行时执行和创建 - 而不是在预编译时。使用eval我们即时执行生成的代码。

并且喜欢macroexpand-1,我们可以查看结果 - 代码 -func1表达式“扩展”,通过删除eval围绕着它——我称之为func2-1:

(defun func2-1 (&rest vals)
  (let ((quoted-values (loop for x in vals
                                     collect `',x)))
    ; do sth with vals here - the func2 function -
    `(func1 ,@quoted-values)))

如果我们运行它,它会立即将最后一个表达式作为代码返回,然后再在func2版本:

(func2-1 (list 1 2 3) (list 4) 5)
;; (FUNC1 '(1 2 3) '(4) '5) ;; the returned code
;; the quoted arguments - like desired!

如果我们使用它来调用它,就会发生这种情况func2(因此评估func1 all:

(func2 (list 1 2 3) (list 4) 5) 
;; ((1 2 3) (4) 5)  ;; the result of (FUNC1 '(1 2 3) '(4) '5)

所以我想说这正是您想要的!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有剩余参数的函数调用带有剩余参数的函数 的相关文章

  • 使 clos 对象可在 lisp 中打印

    如果你想让 common lisp 中的 CLOS 对象可打印 可读打印 你如何在不使用除了 print 和 read 之外的任何东西的情况下做到这一点 至少在我的解决方案中 有两个部分可以做到这一点 但是您将需要这个功能 感谢 cl pr
  • LISP:关键字参数,提供-p

    目前我正在学习 Peter Seibel 的 Practical Common Lisp 在 实用 一个简单的数据库 一章中 http www gigamonkeys com book practical a simple database
  • 如何使用 SBCL 正确保存 Common Lisp 图像?

    如果我想创建我的程序的 Lisp 映像 我该如何正确地做到这一点 有什么先决条件吗 它与 QUICKLISP 配合得很好吗 现在 如果我启动 SBCL 仅预加载 QUICKLISP 并保存图像 save lisp and die core
  • 在lisp中,如何使用floor函数返回的第二个值?

    当我这样做时 4楼3 我得到了 1 1 3 但我该如何使用这 1 3 呢 例如 您可以使用将其绑定到变量multiple value bind multiple value bind quot rem floor 4 3 format t
  • 在 LISP 中实现基本库函数(手动)

    有什么方法可以定义函数my list my cons my append其执行类似的功能list cons and append分别 否则哪里可以找到这些功能的实现呢 Thanks 对于my list和my append 解决方案是 def
  • Lisp 内部引用工作

    口齿不清是如何做到的quote内部工作 例如 quote 1 1 2 似乎相当于 list 1 list 1 2 这意味着它是如何递归地象征 Head 值的 这个功能是内置的吗 Run equal quote 1 1 2 list 1 li
  • Common Lisp 中重置状态

    新手 Common Lisp 问题在这里 有没有办法重置环境状态 我的意思是 是否有一些命令可以使 REPL 恢复到启动后的相同状态 即取消所有变量 函数等 或者如果这不在 Common Lisp 标准中 是否有一些扩展在 SBCL 我使用
  • 用通用函数替换普通函数

    我想将 elt nth 和 mapcar 等名称与我正在原型设计的新数据结构一起使用 但这些名称指定普通函数 因此我认为需要将其重新定义为通用函数 重新定义这些名称可能是一种不好的形式 有没有办法告诉 defgeneric 不要生成程序错误
  • Common Lisp 鼠标位置与 ltk

    我正在 Common Lisp 中制作一个简单的小程序 我想使用鼠标移动来控制它 我用 LTK 作为窗口 我找不到任何可以检索鼠标位置的函数 例如 Emacs Lisp 有 鼠标像素位置 我发现这在罗塞塔代码上 https rosettac
  • 在 Common Lisp 中编写 Lambda 表达式

    我目前正在阅读 Paul Graham 的 ANSI Common Lisp 并且有一个关于编写 lambda 表达式的问题 我们是否需要在 lambda 表达式前面加上前缀 如果我在 REPL 中写这样的东西 它会工作得很好 gt lam
  • 评估 Common Lisp 宏的参数

    我想制作一个宏 其行为取决于它的参数之一 例如 defclass myvar l initarg l reader l defparameter mv1 make instance myvar l 10 defmacro mac1 v pr
  • 从 CCL 检索(加载)源代码?

    我打了电话 load code lisp 用CCL 然后不小心删除了code lisp 有什么办法可以找回源代码吗 CCL 在内存中是否有它 这是一个非常特殊的功能 这里只为克洛祖尔CL 该代码在其他地方不起作用 这在 CCL IDE 中对
  • 试图理解 setf + aref “魔法”

    我现在已经了解了数组和aref在 Lisp 中 到目前为止 它很容易掌握 而且它的作用就像一个魅力 defparameter foo make array 5 aref foo 0 gt nil setf aref foo 0 23 are
  • 如何说服 Lisp SBCL 进行内联 Fixnum 算术?

    我在其他 SO 答案中找到了一些技术 但显然我无法说服 SBCL 进行内联修复数算术 declaim optimize speed 2 safety 1 declaim ftype function fixnum fixnum double
  • 递归分割列表函数 LISP

    split list 函数接受一个列表并返回一个由两个列表组成的列表 其中两个列表由输入的交替元素组成 我写了以下内容 defun split list L cond endp L list NIL NIL t let X split li
  • 为什么我们在 Lisp 中需要 funcall?

    为什么我们必须使用funcall在 Common Lisp 中调用高阶函数 例如 为什么我们必须使用 defun foo test func args funcall test func args 而不是更简单的 defun bar tes
  • Common Lisp 反引号/反引号:如何使用?

    我在使用 Lisp 的反引号读取宏时遇到问题 每当我尝试编写一个似乎需要使用嵌入式反引号的宏时 例如 w x y 来自保罗 格雷厄姆的ANSI 通用 Lisp 第 399 页 我不知道如何以编译的方式编写代码 通常 我的代码会收到一整串错误
  • defvar、defparameter、setf 和 setq 之间有什么区别

    我找到了一个类似问题 https stackoverflow com questions 3855862 setq and defvar in lisp 但我不太明白这个解释 所以我尝试使用以下示例运行 clisp 1 gt defvar
  • 如何在 Common Lisp 中进行模式匹配

    我不知道 Common Lisp 是否存在模式匹配函数 但我必须制作自己的函数 我对Lisp一无所知 有人可以对学习 Lisp 以及最重要的是如何在 Lisp 中进行模式匹配进行提示吗 我必须传递一个模式和一个事实 并判断它们是否匹配 一个
  • Common Lisp 的优先级队列?

    我一直在到处寻找可用的 Common Lisp 优先级队列实现 但到目前为止 我还没有太多运气 由于我对 Common Lisp 相当陌生 每当我看到来自 REPL 的巨大警告 错误转储时 我真的不知道该怎么办 我发现的所有优先级队列实现似

随机推荐