継続

BiwaScheme の継続の挙動を観察している記事を見掛けた。

  • mapのcallbackの中で作られる継続のextentが (多分) mapに戻るまでで,次のコードがうまく動かない:
(define cont (car (map (lambda (x) (call/cc (lambda (c) c))) '(1))))
(cont 3)
cont ; => #<Closure>
     ; Gaucheだと => 3 
http://d.hatena.ne.jp/gengar/20101013/1286904238

R6RS 的には同じ変数に対して再度 define は出来ないので、継続を起動して cont に 3 を define しようとすればエラーになるのが正しい挙動じゃないかと最初は思った。
が、この場合は全体が letrec* であるかのように扱われるはずなので、それを踏まえて考えてみることにした。 R6RS の「Appendix B. Sample definitions for derived forms」の項目に letrec* の定義例がある。

(define-syntax letrec*
  (syntax-rules ()
    ((letrec* ((var1 init1) ...) body1 body2 ...)
     (let ((var1 <undefined>) ...)
       (set! var1 init1)
       ...
       (let () body1 body2 ...)))))

この定義例をあてはめると (cont 3) とした場合、 (set! cont 3) からの継続が起動されるはず。 当初私が思っていたのとは違って、単に set! すると考えられる。 (set! cont 3) の後に (cont 3) が評価され、それはつまり (3 3) なのであるから 3 は手続きではない旨のエラーが通知されるというのが R6RS 的には正しい挙動だと思う。 R5RS だとたぶん未定義。
と、いう解釈でいいかなぁ。

追記

letrec* について注記があることを教えてもらった。

It must be possible to evaluate each without assigning or referring to the value of the corresponding or the of any of the bindings that follow it in . Another restriction is that the continuation of each should not be invoked more than once.
Implementation responsibilities: Implementations must, during the evaluation of an expression, detect references to the value of the corresponding or the of any of the bindings that follow it in . If an implementation detects such a violation of the restriction, it must raise an exception with condition type &assertion. Implementations may or may not detect that the continuation of each is invoked more than once. However, if the implementation detects this, it must raise an exception with condition type &assertion.

http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_idx_408

これによるとやっぱり init のところの継続を再度起動するのはよろしくないらしい。 起動されたのを処理系は検出しなくてもよいともあるわけだけど、検出せずに通過した場合にはどうなるべきなんだろう?
Document ID: 397ea92fe8fe03f219104cefe87ed312