You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Common Lisp实现可变参数接收及展开调用format函数的方法

Common Lisp中可变参数传递给format的实现方法

用过不少语言都支持函数签名里声明可变参数,比如Go里用func doSomething(args ...int)定义,调用时传doSomething(2, 3, 4);Python里用def do_something(*args)定义,调用写do_something(1, 2, 3)。这些语言还都有参数展开/解包语法,比如Go的things = append(things, others...)、Python的do_something_else(*args)。

我想写一个包装函数,接收格式字符串和任意数量的参数,把它们传递给format t。知道format支持可变参数,但没找到正确的实现方式。

尝试的错误代码1:

(defun printf (fstr vals)
  (format t (concatenate 'string fstr "~%") vals))

这个在调用单参数格式字符串时能正常工作,但多参数就报错“too many arguments given to printf”,比如(printf "~d is not ~a" 12 "13")就不行。

又试了这段代码:

(defun printf (fstr &rest vals)
  (format t (concatenate 'string fstr "~%") vals))

这次报错“there are not enough arguments left for this format directive”,显然vals是参数列表,但不知道怎么展开后传给format t。


问题解答

  1. 使用&rest接收可变参数是完全正确的,这正是Common Lisp中定义可变参数函数的标准方式。
  2. 要把vals这个参数列表展开后传递给format,需要用apply函数——它的作用就是把函数调用的参数列表展开,将列表中的每个元素作为单独的参数传给目标函数。

正确的实现代码如下:

(defun printf (fstr &rest vals)
  (apply #'format t (concatenate 'string fstr "~%") vals))

错误原因解释

  • 第一段错误代码的问题是函数只定义了两个参数,无法接收多个可变参数,所以调用时参数数量不匹配报错。
  • 第二段错误代码里,直接把vals传给format,相当于把整个列表作为单个参数传递,但格式字符串需要多个独立参数,所以会提示参数不足。而apply会把vals列表里的元素逐个拆解出来,作为format的后续参数,这样就和直接调用format t "~d is not ~a~%" 12 "13"的效果一致了。

内容的提问来源于stack exchange,提问作者Jonathan Voss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:27:17