在Common Lisp中的值是否只是用于将多个值打包到一个被调用者解构的列表中的语法糖?我问,因为我认为Common Lisp支持"true"多值返回,而不是像其他语言一样返回元组或列表,例如python.有人告诉我,这只是语法糖,所以我希望有人能够解释它.为了尝试理解values函数返回的类型,我输入了(type-of (values 1 2 3)),输出是BIT.我在Common Lisp参考中搜索了这个,我在数据类型部分找不到它.此外,任何人都可以共享一些资源,建议如何在Common Lisp中实现值函数?谢谢.
sds*_*sds 39
Common lisp语言在ANSI 标准 INCITS 226-1994(R2004)中描述,并且具有许多实现.每个人都可以实现多个值,因为它认为合适的,他们是允许的,当然,缺点为他们的列表(事实上,对于CL的的Emacs Lisp兼容层做到了这一点 -但它是,重点和故意,没有一Common Lisp实现).
但是,此工具的目的是允许传递(至少一些)多个值而不进行(即,不分配堆内存)和我知道的所有CL实现.从这个意义上讲,多值设施是一种优化.
当然,对于不同的平台和场景,此功能的实现可能会有很大差异.例如,前几个(例如,20 - 标准所需)存储在线程局部向量的静态中,接下来的几个(1000?)在堆栈上分配,其余的(如果需要)分配在堆作为矢量或列表.
例如,该函数floor返回两个值.如果你写
(setq a (floor 10 3))
Run Code Online (Sandbox Code Playgroud)
你只捕获第一个并丢弃第二个,你需要写
(setf (values q r) (floor 10 3))
Run Code Online (Sandbox Code Playgroud)
捕获两个值.这与其他语言可能表达的类似
q,r = floor(10,3)
Run Code Online (Sandbox Code Playgroud)
使用元组,除了CL 没有分配内存来传递(只是几个)多个值,而其他语言经常这样做.
IOW,人们可以将多个值视为一个短暂的结构.
请注意,CL可以将多个值转换为列表:
(destructuring-bind (q r) (multiple-value-list (floor 10 3))
; use q & r here
...)
Run Code Online (Sandbox Code Playgroud)
而不是更有效和简洁
(multiple-value-bind (q r) (floor 10 3)
; use q & r here
...)
Run Code Online (Sandbox Code Playgroud)
CL也不具有用于"多值对象"精确,因为它的特殊类型的未分配一个单独的对象以绕过多个值.在这个意义上,人们可以确实声称这values是语法糖.
(declaim (ftype (real &optional real) (values real real)) floor)
Run Code Online (Sandbox Code Playgroud)
这意味着floor返回两个值,两个reals(而不是返回类型的值(values real real)),即,在这种情况下,可能会声称滥用符号.
在您的特定情况下,type-of是一个普通的函数(即,不是宏或特殊运算符).你传递一个对象,1,因为,除非你使用multiple-value-bind和朋友,只使用第一个值,所以
(type-of (values 1 2 3))
Run Code Online (Sandbox Code Playgroud)
是完全相同的
(type-of 1)
Run Code Online (Sandbox Code Playgroud)
和类型1是bit.
一种用途values是控制函数的返回值.通常,CL函数的返回值是最后一种形式的返回值.有时候,这是不可取的,例如,最后的形式返回多个值,你希望你的函数返回一个值(或根本没有,像void中C):
(defun 2values (x y)
(floor y x))
(defun 1value (x y)
(values (floor y x)))
(defun no-values (x)
(print x)
(values))
Run Code Online (Sandbox Code Playgroud)
Xac*_*ach 12
该values函数不仅仅是用于为调用者进行解构的列表的语法糖.
例如,如果调用者只需要一个值,它将从返回多个值的表单中只获得一个值(第一个),而不是列表.由于type-of只接受一个值作为参数,因此它为您提供第一个值的类型,1.是BIT类型.
每个Common Lisp实现都可以自由地实现自己的策略来实现多个值.我从Frode Fjeld写的关于他的实现Movitz如何在The Movitz开发平台第2.5节中处理它的内容中学到了很多东西.