多値

Common Lispでは関数は値を0個以上返す.これまでは主に1つの値を返す場合の記述をしてきた.本頁では0個の値を返す,つまり値を返さない場合や2個以上の値を返す場合について記述する.
多値を返す
多値を受け取る
多値を他の関数に渡す
multiple-value-list

多値を返す

多値を返す関数としてvaluesがある.
(values 値 値 値…)
valuesは引数の値をすべて返す.以下に例を示す.

(values 1 2 3)
1 ;
2 ;
3
このvaluesを関数の最後に実行すれば,多値を返す関数を作成することができる.以下は三つの引数をそのまま返す関数である.
(defun hoge (a b c)
(values a b c))
HOGE

(hoge 1 2 3)
1 ;
2 ;
3

多値を受け取る

今までのやりかたでは,関数から多値を受け取ることはできない.

(defun hoge (a b c)
(values a b c))
HOGE

(setf x (hoge 1 2 3))
1
x
1
関数から多値を受け取るにはmultiple-value-bindを使用する.
(multiple-value-bind リスト 多値関数呼び出し 式 式 式…)
multiple-value-bindを使用すると,リストに多値関数の返り値が格納される.
(multiple-value-bind (x y z) (hoge 1 2 3)
(format t “~A,~A,~A~%” x y z))
1,2,3
NIL
x

*** – EVAL: variable X has no value
ここで,x,y,zはmultiple-value-bind式内でのみ有効であることに注意する.multiple-value-bindの第一引数のリストの要素数が多値関数の返り値の数より少なければ,足りない分は単に捨てられる.

(multiple-value-bind (x y) (hoge 1 2 3)
(format t “~A,~A~%” x y))
1,2
NIL
逆にmultiple-value-bindの第一引数のリストの要素数が多値関数の返り値の数より多ければ,多い分にはNILが格納される.
(multiple-value-bind (x y z aa) (hoge 1 2 3)
(format t “~A,~A,~A,~A~%” x y z aa))
1,2,3,NIL
NIL
multiple-value-bindの返り値は,最後に実行された式の値である.
(multiple-value-bind (x y z) (hoge 1 2 3) ‘a)
A
(multiple-value-bind (x y z) (hoge 1 2 3) ‘a ‘b)
B

多値を他の関数に渡す

multiple-value-callを使用すると,多値を関数の引数に渡すことができる.
(multiple-value-call 関数 多値関数)
以下はhogeから返る多値をfugaに渡す例である.
> (defun fuga (x y z)
(values x y z (+ x y z)))
FUGA
> (multiple-value-call #'fuga (hoge 1 2 3))
1 ;
2 ;
3 ;
6

multiple-value-list

(multiple-value-call #'list 多値関数)
と同等のものとして
(multiple-value-list 多値関数)
がある.
> (multiple-value-call #'list (hoge 1 2 3))
(1 2 3)
> (multiple-value-list (hoge 1 2 3))
(1 2 3)
multiple-value-listは多値関数の返り値をリスト化することが比較的多いことから作成されたのだと思う.

This article was written by Fujiko