首页 文章

Common Lisp中的值函数

提问于
浏览
24

这些值是Common Lisp中的函数,只是用于将多个值打包到一个被调用者解构的列表中的语法糖 . 我问,因为我认为Common Lisp支持"true"多值返回,而不是像其他语言一样返回元组或列表,例如python . 有人告诉我,这只是语法糖,所以我希望有人能够解释它 . 为了尝试理解values函数返回的类型,我键入 (type-of (values 1 2 3)) ,输出为 BIT . 我在Common Lisp参考中搜索了这个,我在数据类型部分找不到它 . 此外,任何人都可以共享一些资源,建议如何在Common Lisp中实现值函数?谢谢 .

3 回答

  • 1

    CL中的多个值

    语言Common lisp在ANSI标准INCITS 226-1994(R2004)中描述,并且具有许多实现 . 每个人都可以按照自己认为合适的方式实现multiple values,当然,他们可以为他们列出一个列表(事实上,the Emacs Lisp compatibility layer for CL does just that - 但是,重点和故意, not 是一个Common Lisp实现) .

    目的

    但是,此工具的目的是允许传递(至少一些)多个值而不进行(即,不分配heap内存)和我知道的所有CL实现都这样做 . 从这个意义上说,多值设施是一种优化 .

    当然,对于不同的平台和场景,此功能的实现可能会有很大差异 . 例如,前几个(例如,20 - required by the standard)存储在线程局部向量的静态中,接下来的几个(1000?)在堆栈上分配,其余的(如果需要)在堆上分配为向量或名单 .

    用法

    例如,函数floor返回两个值 . 如果你写

    (setq a (floor 10 3))
    

    你只捕获第一个并丢弃第二个,你需要写

    (setf (values q r) (floor 10 3))
    

    捕获两个值 . 这类似于other languages可能表达的内容

    q,r = floor(10,3)
    

    使用tuples,除了CL没有分配内存来传递(只是几个)多个值,而其他语言经常这样做 .

    IOW,人们可以将多个值视为一个短暂的结构 .

    请注意,CL可以将多个值转换为列表:

    (destructuring-bind (q r) (multiple-value-list (floor 10 3))
      ; use q & r here
      ...)
    

    而不是更有效和简洁

    (multiple-value-bind (q r) (floor 10 3)
      ; use q & r here
      ...)
    

    MV&type

    CL确实 not 具有"multiple value object"的特殊类型,因为它没有分配单独的对象来传递多个值 . 从这个意义上讲,人们可以确实声称 values 是语法糖 .

    但是,在CL中,可以声明function type返回multiple values

    (declaim (ftype (real &optional real) (values real real)) floor)
    

    这意味着 floor 返回两个值,均为real s(而不是返回类型 (values real real) 的值),即,在这种情况下,可能会声称滥用符号 .

    你的情况

    在您的特定情况下,type-of是普通函数(即,不是宏或特殊运算符) . 你传递一个对象,1,因为,除非你使用multiple-value-bind和朋友,只使用第一个值,所以

    (type-of (values 1 2 3))
    

    是完全相同的

    (type-of 1)
    

    和类型1是bit .

    PS:控制返回值

    values的一个用途是控制函数的返回值 . 通常,CL函数的返回值是最后一种形式的返回值 . 有时它是不可取的,例如,最后一个表单返回多个值,并且您希望函数返回一个值(或者没有,如 C 中的void):

    (defun 2values (x y)
      (floor y x))
    (defun 1value (x y)
      (values (floor y x)))
    (defun no-values (x)
      (print x)
      (values))
    
  • 11

    values 函数不仅仅是用于为调用者进行解构的列表的语法糖 .

    首先,如果调用者只需要一个值,它将从返回多个值的表单中只获得一个值(第一个),而不是列表 . 由于 type-of 只接受一个值作为参数,因此它为您提供第一个值的类型,1 . 类型为BIT .

    每个Common Lisp实现都可以自由地实现自己的策略来实现多个值 . 我从Frode Fjeld写的关于他的实现,Movitz如何在The Movitz development platform,第2.5节中处理它的内容中学到了很多东西 .

  • 36

    如果你进行CL实现,你可以用列表实现它,只要它符合规范 . 你需要处理一个特定的值,你需要一些方法来标记零,2..n值,其他函数需要理解格式和打印可以使其显示方式与其他品牌相同 .

    最有可能 values 及其姐妹函数是一种优化,其中实现使用堆栈而不是将值传递给列表结构只是为了让它在下一级别进行解构 . 在没有浪费RAM和CPU的旧时代,这非常重要,但我怀疑如果你今天使用 destructuring-bind 而不是 multiple-value-bind ,你会发现真正的麻烦 .

    Common Lisp与Scheme的不同之处在于你可以创建一个函数,例如 . floor 在其中的计算结果除了商答案之外还有余数,返回全部值同时但您可以使用它,就像它只返回第一个值一样 . 我真的很想念有时候编写Scheme,因为它要求你有一个类似于_600126的 call-with-values 或像 let-values 这样的语法糖来处理所有返回的值,这再次让你最终得到三个版本,以防你只需要一个值 .

相关问题