MIT Schemeの多値が多値じゃない問題
SECDV VMのインタプリタできた。後で何か書く。https://github.com/okuoku/yuni/commit/42b819b3ca09f716eb2f180d54065a4291e313e3 基本的にスムースに動いて後はヒープとかコンパイラを残すのみだけど、MIT Schemeの微妙な多値の実装に半日悩んだ。
MIT Schemeの多値、つまりcall-with-values手続きとvalues手続きはこのように実装されている。
(define (values . objects) (lambda (receiver) (apply receiver objects))) (define (call-with-values thunk receiver) ((thunk) receiver))
... 確かに、MIT-Schemeのドキュメントには、
Thunk must return multiple values using the values procedure.
と有るのでこういう実装でも良いんだろうけど、大抵のScheme処理系は、
(call-with-values (lambda () 1) (lambda (value) value))
のようにして、1値をvalues手続きを使わずに返すことは許している。MIT Schemeのこの制約がR5RS/R7RS的にオッケーなのかどうかはまだちゃんと調べていないが、yuniではとりあえず
(define (call-with-values thunk receiver) ;; override ;; See src/runtime/global.scm for actual impl. (let ((t (thunk))) (cond ((procedure? t) (t receiver)) (else (receiver t)))))
call-with-valuesを1値の場合の専用処理を加えた形にoverrideすることで対策した。当然コレではgenericにはダメで、多値を期待されたthunkが、手続きオブジェクトの1値を返す場合にうまく動かない。