多値と関数合成

PLT Scheme のレファレンス・マニュアルを読んでいてちょっと驚いたことがあるので書きます。

compose 関数で合成する関数の中に、多値を返す関数を入れられるんですよ:

(map (compose list split-path path->complete-path)
     (directory-list))
; => ((#<path:C:\home\desktop\> #<path:onlisp.pdf> #f) ...)

(split-path が多値を返す関数です)

もしかして Scheme では普通なんでしょうか?

どうやっているのか気になって、compose の定義 (collects/scheme/private/list.ss 内) を調べてみると

(compose f g)

とある時に、f の引数の数を procedure-arity という関数で調べ、それが 1 でない場合は call-with-values で g の適用結果を f に渡す、ということをしていました:

(call-with-values
  (lambda () (g a))
  f)

なるほどなという感じです。

でも、関数の引数の数は分かるとしても、返り値の数までは知り得ないですよね? もし g が多値を返さない関数でも call-with-values を使って良いんでしょうか?

(call-with-values (lambda () 1) list)
; => (1)

あ、1値でも使えるんですね。知らなかったです。