Reasoned Schemer (110) condu、onceo
conda
は成功した節で止まってくれるとはいえ成功した節から帰ってこなくては無力
> (run* q (conda ((alwayso) succeed) (succeed fail)))
(no value)
run 1
なら帰ってくる
> (run 1 q (conda ((alwayso) succeed) (succeed fail)))
'(_0)
そこでcondu
の登場
condu
は一度questionが成功したらそれで終わり 帰ってくる
> (run* q (condu ((alwayso) succeed) (succeed fail)))
'(_0)
run 1
と同じ、と言っていいのかな?
これは帰ってこない
> (run* q (condu (succeed (alwayso)) (succeed fail)))
(no value)
なんで?
あー「一度成功したら」はあくまでquestionだけの話なのか
answerはいつもと同じで何度でも成功できるわけね
じゃあrun 1
にすると?
> (run 1 q (condu (succeed (alwayso)) (succeed fail)))
'(_0)
これは成功するのかー
run 1
は全体で1回成功したら打ち切りだから違いが出てくるのかな
condu
の定義
(define-syntax condu
(syntax-rules ()
((condu (g0 g ...) ...)
(conda ((once g0) g ...) ...))))
conda
のquestionにonce
をかけている
やってることそのままって感じだな
once
はこう
(define (once g)
(lambda (s)
(let loop ((s-inf (g s)))
(cond
((null? s-inf) '())
((pair? s-inf)
(cons (car s-inf) '()))
(else (lambda () (loop (s-inf))))))))
形はifte
と似ている
g
が失敗したら失敗
成功したら、ifte
ではappend-map-inf
してたところで要素ひとつのリストを返す
なるほどonceだ
なおcondu
もThe Second Commandmentを守る必要あり
condu
を使ってonceo
を作る
(defrel (onceo g)
(condu (g succeed) (succeed fail)))
こうなる
> (run* x (teacupo x))
'(tea cup)
> (run* x (onceo (teacupo x)))
'(tea)
teacupo
が1回しか成功しないってことね