恒等関数としての values
再び多値関連の小ネタです。
PLT Scheme のあるライブラリを見ていて、こんな values の使い方を発見しました。
(filter values (list ...))
一瞬 values が再定義されているのかな?と思って辺りを探したんですが何も無く、試しにやってみると
> (filter values '(1 2 #f 3 4 #f 5)) (1 2 3 4 5)
おお。
> (map values '(1 2 #f 3 4 #f 5)) (1 2 #f 3 4 #f 5)
なるほど。
前回驚いた時と同様、「多値」イコール「2つ以上の値」という固定観念から抜け出せていなかったようです。このように1つの値に適用された場合は、ただの恒等関数 (\x = x) として機能するわけですね。
じゃぁ0値の場合はどうなるんでしょうか?
> (values) >
REPL での見かけ上は void 値を評価した時と同じです:
> (void) >
ということは?
> (void? (values)) context expected 1 value, received 0 values === context === d:\MzScheme\collects\scheme\private\misc.ss:68:7
おぉ、void ですら無い、と。
じゃぁこんな風に0引数関数を呼ぶこともできる、ということですね
> (call-with-values (lambda () (values)) (lambda () 'nullary)) nullary
理解しました。
応用すると、適当に値を集めてきてその数によって分岐処理をする、みたいな事も可能になるわけです:
(call-with-values (lambda () (apply values variable-length-list)) (case-lambda (() 'nullary) ((x) 'unary) ((x y) 'binary)))