kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

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回しか成功しないってことね