2007/02/28

答えはわかってるっていう問題は少なくない(実際、答えは42だ)。
問いをはっきりさせるのに抽象化が必要なんだと思う。

2007/02/17

連番を作りたい。ようするに、こんな動作をするプロシージャintegがほしい。
gosh> (list (integ) (integ) (integ))
(1 2 3)
まあ、グローバル変数を破壊的に更新すればいい。
(define n 0)
(define (integ)
(set! n (+ n 1))
n)
でもそんなSchemeコードはいやだ。主に気分的な理由で。こういう問題にはcall/ccを使うのがオレブーム。
(define (integ)
(let R ((n 0))
(call/cc
(lambda (k)
(set! integ (lambda () (R (+ n 1))))
(+ n 1)))))
しかしこれではcall/ccの意味がまったくありませんでした。すみません。以下で十分です。
(define (integ)
(let R ((n 0))
(call/cc
(lambda (k)
(set! integ (lambda () (R (+ n 1))))
(+ n 1)))))

気を取り直して。応用。
(let R ((str "hello hello hello hello"))
(rxmatch-if (rxmatch #/ / str)
(space)
(R (regexp-replace space str #`",(integ)"))
str))

=> hello1hello2hello3hello"
Gaucheに用意されているregexp-replace-allという便利な関数と組み合わせると編集者にとってはプチよろこばしい。
gosh> (regexp-replace-all #/ / "hello hello hello hello" (lambda (m) (integ)))
"hello4hello5hello6hello"

ところでintegを次のように定義するとうまくいかない理由を昨日から考えているんだけど、わからない。これでもとくに問題なさそうなんだけど、(list (integ) (integ)) のように実行しても1つめの(integ)が評価されるだけ。
(define (integ)
(call/cc
(lambda (skip)
(let R ((n 0))
(call/cc
(lambda (k)
(set! integ (lambda () (k '())))
(skip (+ n 1))))
(R (+ n 1))))))