现在的位置: 首页 > 综合 > 正文

Lisp.多值(Multiple values)

2013年09月12日 ⁄ 综合 ⁄ 共 1106字 ⁄ 字号 评论关闭

有人曾经说过,为了强调函数式编程语言的重要性,都要说每个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是一样的效果。

抱歉!评论已关闭.