lisp - 访问器 VALUES 作为定义的最后一种形式,其返回值为 void 或可忽略

标签 lisp common-lisp return-value

在阅读其他开发人员编写的 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 中,ListenersTrace dialog 保留对结果的引用,直到它们被清除 1
    • 在 LispWorks 的 IDE 中,Tracer工具保留对结果的引用 输出数据 View ,直到它们被清除
    • 在 SLIME 中,REPL 在 presentations 中保留对结果的引用 直到他们被清除

非优势/非问题:

  • 有些编译器生成的指令较少,有些编译器生成的指令较多,但除非 你正在处理字节和/或周期,这是可以忽略不计的
  • 您已经不需要返回任何值,例如:
    • 当您希望调用者区分返回值的数量时
      这可能也暴露了定义的糟糕设计
    • 当结果应该用于 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/

相关文章:

macos - 没有 Xcode 的应用内购买(苹果应用商店)

c# - 如果可能的话,如何使方法的返回值可选?

C:从函数中的循环中删除多个值的方法

lisp - 从另一个列表的原子在 LISP 中构建列表

sorting - 如何使用子列表对列表进行排序(常见的 Lisp)

lisp - 使用 Lisp 或 PROLOG 从列表中删除元素的外观

regex - 为什么将代码作为函数调用比直接在 Clozure Common lisp 中调用要花更长的时间?

Java传递值

emacs - 如何自定义 volatile-highlights 背景颜色?

list - 如何在 Emacs Lisp 中设置列​​表中的部分参数?