Prolog 写経記 その 90 repeat/1
(ほぼ) 毎日淡々と Prolog を写経します.元ネタはこちら.
- 作者: ボグダンフィリピッチ,中島誠,伊藤哲郎
- 出版社/メーカー: 海文堂出版
- 発売日: 1990/08
- メディア: 単行本
- 購入: 4人 クリック: 33回
- この商品を含むブログ (68件) を見る
repeat/1
を写経します.順番的には
for/1
なのですが,その中で repeat/1
を使ってるのだ.モード
repeat(+)
ふむ.
定義
では,こいつの定義を写経しませう.
:- op(900, fx, repeat). :- op(850, xfx, until). repeat Q until P :- repeat, call((Q, !)), call(P).
すっかりお馴染みのオペレータ宣言に,随分シンプルな述語の本体.
ちょっと引っかかるのは述語本体の
call((Q, !)),
でしょうか.ここには「Q
についてのバックトラックはない」という注釈が付いています.
さらに,「注記」に重要なことが書いてあるのでそちらを先に.
注記
repeat/1
はP
が失敗したときQ
についてのバックトラックをせず,むしろQ
を再度呼び出す.repeat/1
とみ込み述語のrepeat/0
を取り違えないように.
ふむ.
つ・ま・り
述語の定義にある
call((Q, !)),
のカットがないと,繰り返しの終了条件 P
が失敗する度に,つまり繰り返しの度に繰り返しの本体 Q
がバックトラックされちゃうということですね.
それは困るのでカットが必要,と.なるほど.
例
では使用例を写経しませう.
get_filename(F) :- repeat ( write('Filename?'), read(F) ) until exists_file(F).
これまた対話的ですね.
これの使用例はないので適当に試すべし.
2 ?- get_filename(F). Filename?'util.swi'. F = 'util.swi' Yes 3 ?- get_filename(F). Filename?notfound. Filename?'memo.swi'. F = 'memo.swi' Yes
ふむ.