define-valuesの書き方
コメントを頂いた。
(define-syntax define-values (syntax-rules () ((define-values () exp) (call-with-values (lambda () exp) (lambda () 'unspecified))) ((define-values (var . vars) exp) (begin (define var (call-with-values (lambda () exp) list)) (define-values vars (apply values (cdr var))) (define var (car var)))) ((define-values var exp) (define var (call-with-values (lambda () exp) list)))))
これは一旦listにして分解する方法。たしかにこちらの方が多少書きやすいかもしれない。。
R6RS Schemeでは多少修正が必要で、
(define-syntax define-values (syntax-rules () ((define-values () exp) (call-with-values (lambda () exp) (lambda () 'unspecified))) ((define-values (var . vars) exp) (begin (define temp (call-with-values (lambda () exp) list)) ;; var → temp (define-values vars (apply values (cdr temp))) (define var (car temp)))) ((define-values var exp) (define var (call-with-values (lambda () exp) list)))))
(define var ...)が一度しか表れないようにしないといけない。R6RSでは2重のdefineはできない。また、このままだとTop Level以外では使えないので、結局無駄な値をdefineする必要は有る。
(define-syntax define-values (syntax-rules () ((define-values () exp) (define bogus ;; defineに変える。 (call-with-values (lambda () exp) (lambda () 'unspecified)))) ((define-values (var . vars) exp) (begin (define temp (call-with-values (lambda () exp) list)) (define-values vars (apply values (cdr temp))) (define var (car temp)))) ((define-values var exp) (define var (call-with-values (lambda () exp) list)))))
一旦多値をlistに纏めないといけないのは、マクロのパタン変数で多値を取り扱えないため。そのかわり、set!を使わずに済むので、前のように変数をexportするために余計な変数を準備する必要はなくなる。
多値を分解せず、かつ、set!を使わない方法は存在しないように思える。
- 多値を分解せずbindする方法はlambda(あるいはreceive)しかない
- lambdaは常にスコープを作る
スコープを越える方法はset!しかない。と思う。