今日は,『プログラミングGauche』の
- 19章 継続(昨日からの継続…)
- 20章 モジュールシステム
- 21章 デバッグ
を読みました。
19章
昨日,読んでほとんど意味が分からなかったので,今日も取り組んでいます。
http://ja.wikipedia.org/wiki/%E7%B6%99%E7%B6%9A の中で,
とありましたので,今日はちょっと趣向を変えて,Rubyで継続について勉強してみます。
「Rubyで継続で末尾再帰最適化まがいの行為をした」にcallccを用いた1+2+3+…+nを求めるプログラムがありました。以下です。
def sum(n) acc = 0 cc = nil callcc {|i| cc = i} case n when 0 then acc else n, acc = n - 1, acc + n; cc.call end end puts sum(10)
ccはContinuationクラスのインスタンスなので,cc.callとすることで,case n以下を実行するんだろうと思います(nが0になったら停止です)。なんとなく,ほんの少し継続についてイメージがわいてきたので,Gaucheで書いてみたのが,以下です。
(define (sum n) (let ((acc 0) (cc #f)) (call/cc (lambda (i) (set! cc i))) (cond [(eq? n 0) acc] [else (set! acc (+ acc n)) (set! n (- n 1)) (cc)])))
Ruby版の1行1行をそのまま書いてみました。実行すると,一応動きます。
gosh> (sum 10)
55
21章
P332に「21.7 マクロの調査」があります。その中で,aifをマクロ定義しているのですが,この中で使われている「@」は何の意味があるのでしょう?
(define-macro (aif test-form then-form . else-form) `(let ((it ,test-form)) (if it ,then-form ,@else-form)))
不思議に思って,「@」無しのaif2も定義してみました。
(define-macro (aif2 test-form then-form . else-form) `(let ((it ,test-form)) (if it ,then-form ,else-form)))
aifとaif2を実行してみます。
gosh> (define m '(shiro nobsun yasuyuki cut-sea)) m gosh> (aif (member 'yasuyuki m) (car it) "Not Found") yasuyuki gosh> (aif2 (member 'yasuyuki m) (car it) "Not Found") yasuyuki
両者に違いはありません…。しかし,「@」はelse-formについていたので,以下を試してみると,
gosh> (aif (member 'rahaema m) (car it) "Not Found") "Not Found" gosh> (aif2 (member 'rahaema m) (car it) "Not Found") *** ERROR: invalid application: ("Not Found")
両者に違いが現れました。macroexpandで展開してみると,
gosh> (macroexpand '(aif (member 'rahaema m) (car it) "Not Found")) (let ((it (member 'rahaema m))) (if it (car it) "Not Found")) gosh> (macroexpand '(aif2 (member 'rahaema m) (car it) "Not Found")) (let ((it (member 'rahaema m))) (if it (car it) ("Not Found")))
となりました。
しかし,この「@」,探し方が悪かったんだろうと思うのですが,本の中にもGaucheユーザリファレンスにも説明を見つけることはできませんでした…。
追記
上記の件ですが,id:SaitoAtsushiさんに教えていただきました。ありがとうございます。
http://practical-scheme.net/gauche/man/gauche-refj_30.html#IDX68 を見て理解しました。