有人曾经说过,为了强调函数式编程语言的重要性,都要说每个Lisp表达式都返回一个值。现在事情没有那么简单了;在Common Lisp中,一个表达式可以返回0个或多个值。返回值的最大个数根据实现的不同而不同。
多值允许函数计算并返回几个东西,并且不需要建立一个结构来保存它们。比如,内置的函数get-decoded-time返回当前的时间,这个时间用9个值来表示:秒,分钟,小时,日期,月,日,还有其它两个东西。
多值也是的我们在写函数的时候可以区分找到nil和找不到一些东西的情况。这也就是为什么gethash返回两个值。因为它使用第二个值来标识是成功或是失败,我们可以在一个哈希表表中存储nil,就像是存储其它值一样。
函数values返回多值。他就是返回了你传递给它的参数:
[30]> (values 'a nil (+ 2 1)) A ; NIL ; 3
如果一个values表达式是一个函数中最后被求值的,那么它的返回值也就变成这个函数的返回值。多值在多个返回中被完整地传递:
[32]> ((lambda () ((lambda () (values 1 2))))) 1 ; 2
然而,有时候只需要一个值,除了第一个外其它的都要被舍弃掉:
[33]> (let ((x (values 1 2))) x) 1
不给values任何参数,它可能不会返回任何值。这种情况下,如果你想从中获取一个值,你就会获得nil:
[36]> (values) [37]> (let ((x (values))) x) NIL
要想接收到多值,我们使用multiple-value-bind函数:
[39]> (multiple-value-bind (x y z) (values 1 2 3) (list x y z)) (1 2 3) [40]> (multiple-value-bind (x y z) (values 1 2) (list x y z)) (1 2 NIL)
如果变量比值多,那么多出来的就是nil了。如果值比变量多,那么多于的值就会被丢弃掉。所以如果我们想只打印时间,我们就可以这样写:
[42]> (multiple-value-bind (s m h) (get-decoded-time) (format nil "~A:~A:~A" h m s)) "16:5:4"
你可以通过multiple-value-call将多值应用到第二个函数上:
[43]> (multiple-value-call #'+ (values 1 2 3)) 6
还有一个函数:multiple-value-list:
[44]> (multiple-value-list (values 'a 'b 'c)) (A B C)
其实这和调用multiple-value-call,将其第一个参数设置为#'list是一样的效果。