多値を返す関数
以前のエントリで、Scheme で多値を返す関数について shiro さんに教えて頂いたのですが……
(define (dvals a b) (values a b)) => dvals
という余り意味の無い、多値を返す関数を定義して評価すると、
(dvals 1 2) => 1, 2
となります。
ここで `dvals' は、二つの引数を取り、それぞれをそのまま返す関数なので、そのまま再帰的に利用できるかと思いきや……
(dvals (dvals 1 2)) *** ERROR: wrong number of arguments for #<closure dvals> (required 2, got 1) Stack Trace: _______________________________________ 0 (report-error e) At line 167 of "/usr/local/share/gauche/site/lib/igauche.scm" 1 (call/cc (lambda (break-inner-read-eval-print-loop) (define (reade ... [unknown location]
と怒られてしまいます。
ああ、ここで shiro さんからご指摘頂いた、`call-with-values' を使うんですね。
(call-with-values (dvals 1 2) dvals) *** ERROR: invalid application: (1) Stack Trace: _______________________________________ 0 (report-error e) At line 167 of "/usr/local/share/gauche/site/lib/igauche.scm" 1 (call/cc (lambda (break-inner-read-eval-print-loop) (define (reade ... [unknown location]
そうですね、Gauche の Info には、
6.15.4 多値
- -
(snip)
-- 機能: call-with-values producer consumer
[R5RS] 手続きPRODUCERを引数無しで呼びます。そして、それが返した値
を引数としてCONSUMERを呼びます。CONSUMERが返す値を 返します。
(call-with-values (lambda () (values 1 2)) cons)
=> (1 . 2)
とありますから、
(call-with-values (lambda () (dvals 1 2)) dvals) => 1, 2
とするしかないのでしょうかね。
むう、これしかないすると再帰的には利用できないということになるのでしょうか。
高階関数として適用する方向に持って行かないとダメなのでしょうかね。
今日は時間が無くなってしまいましたのでまた今度。