在阅读其他开发人员编写的 Commom Lisp 代码时,我注意到其中一些 调用VALUES访问器,而不以最后形式的定义提供任何参数,其返回值是无效的或可忽略的。
例子:
(defun definition-whose-return-values-are-neglectable ()
... Some s-expressions ...
(values))
将此形式添加为这些类型定义中的最后一个表达式是否有任何优势(对于编译器、性能等)?
最佳答案
(values)
last 形式的优点或主要用例是:
- 当返回值对于定义没有意义时的 self 记录代码
- 通常,避免开发工具处理或保留对
被忽视或不必要的结果;
具体来说:- 避免在 REPL 中打印长序列或无限序列,以防万一
*print-circle*
设置为t
,*print-length*
设置为无
,*print-level*
设置为无
, 或类似的任何特定于实现的参数 - REPL 集
*
为nil
作为无值被视为的结果无
,并设置/
到一个空列表 - 在 Allegro CL 的 IDE 中,Listeners和 Trace dialog 保留对结果的引用,直到它们被清除 1
- 在 LispWorks 的 IDE 中,Tracer工具保留对结果的引用 输出数据 View ,直到它们被清除
- 在 SLIME 中,REPL 在 presentations 中保留对结果的引用 直到他们被清除
- 避免在 REPL 中打印长序列或无限序列,以防万一
非优势/非问题:
- 有些编译器生成的指令较少,有些编译器生成的指令较多,但除非 你正在处理字节和/或周期,这是可以忽略不计的
- 您已经不需要返回任何值,例如:
- 当您希望调用者区分返回值的数量时
这可能也暴露了定义的糟糕设计 - 当结果应该用于
multiple-value-call
表格
这可能也暴露了调用者的不良设计,这实际上有一面 形式之间的影响
除了消除副作用或允许 在整个multiple-value-call
之前或之后发生的副作用
- 当您希望调用者区分返回值的数量时
问题:
- 通常,它会禁用定义中的尾调用优化
然而,足够聪明的编译器可能会检测到对无值定义的尾调用, 通常在ftype
的帮助下declare
s/declaim
秒, 并在这些调用中应用优化
这并非没有更改其他定义的风险,所以我的猜测是 没有实现
1. 您可以通过设置历史来清除 Allegro CL 中某个 Listener 的历史记录 大纲的内容到一个空列表:
(setf (cg:range (cg:find-component
:history-outline
(first (cg:toolbars ide.base:*listener-window*))))
'())
关于lisp - 访问器 VALUES 作为定义的最后一种形式,其返回值为 void 或可忽略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16809766/