Scheme:多値の分配

Scheme:多値の分配

Scheme:多値で出た議論

セマンティックスとか継続との絡みは良く分かってないのですが、 対称性という意味でいうと、

 (func0 (func1 arg1) (func2 arg2) (func3 arg3) ...)
 => (func0 val1 val2 val3 ...)

という風に複数の式からの返り値を引数にとる。 これが n-in だとすると

 (???? func1 func2 func3 ... (values val1 val2 val3 ...))

=> どういう動作になるかは分からないけど UNIX の fork みたいな感じで

 (func1 val1)   (func2 val2)   (func3 val3) ....

というスレッドの分岐みたいのが起こるのが m-out な気がしちゃうなぁ。

 (apply func arg1 arg2 ...)

という n-in に対して

 (apply-val-to-funcs values func1 func2 func3 ...)

で、 values が多値を返す式、 とすると apply-val-to-funcs は call-with-values に相当するやつみたいなイメージなんだけど、個人的には。 values の返す複数の値が順に func1 func2 ... にばらまかれるような感じ。 cut-sea:2004/06/03 14:32:51 PDT

実装

teranishiさんによる実装例

(define-syntax call-each-values
  (syntax-rules ()
    ((_ (func funcs ...) args ...)
     (call-each-values "gensym" () () (args ...) (funcs ...) (func funcs ...) (args ...)))
    ((_ "gensym" l (lr ...) () () (func ...) (args ...))
     (call-each-values "bind" (l lr ...) (l lr ...) (func ...) (args ...)))
    ((_ "gensym" l (lr ...) () (f g ...) (func ...) (args ...))
     (call-each-values "gensym" () (l lr ...) (args ...) (g ...) (func ...) (args ...)))
    ((_ "gensym" (tr ...) (lr ...) (a b ...) (f ...) (func ...) (args ...))
     (call-each-values "gensym" (t tr ...) (lr ...) (b ...) (f ...) (func ...) (args ...)))
    ((_ "bind" (() ...) ((l ...)  ...) (func ...) ())
     (values (func l ...) ...))
    ((_ "bind" ((v vr ...) ...) ((l ...) ...) (func ...) (arg args ...))
     (receive (v ...) arg (call-each-values "bind" ((vr ...) ...) ((l ...) ...) (func ...) (args ...))))))

使用例

(define (qr-list a b)
  (if (or (null? a) (null? b))
    (values () ())
    (call-each-values (cons cons)
      (quotient&remainder (car a) (car b))
      (qr-list (cdr a) (cdr b)))))

gosh> (qr-list '(10 9 8 7 6) '(5 4 3 2 1))
(2 2 2 3 6)
(0 1 2 1 0)

見てくれが通常の再帰に近くなるし、一時変数を使う必要もありません。

Tag: 多値


Last modified : 2008/07/24 03:00:51 UTC