Debian GNU/LInuxでPrologを始める
SWI-Prologのインストール
DebianではGNU Prologを使う選択肢もあるが、ここではSWI-Prologを使うので、swi-prologまたはswi-prolog-xというdebパッケージをインストールする。後者はGUIアプリケーションを開発するためのXPCEというツールキットが含まれているパッケージ。
$ su # apt update # apt install swi-prolog # exit
SWI-Prologの起動
インストールが無事に完了したらPrologを起ち上げる。swiplかprologと打ち込んでエンターキーを押せば起動する。
$ swipl
$ prolog
いろいろなメッセージが表示された後、次のようなプロンプトが表示される。
?-
まずはお決まりのHello World!を表示。
?- format('Hello World!'). Hello World! true. ?-
次に四則演算。
?- is(A, 5+7). A = 12. ?- is(S, 5-7). S = -2. ?- is(M, 5*7). M = 35. ?- is(D, 5/7). D = 0.7142857142857143. ?-
A, S, M, Dはいずれも変数。変数名の先頭は大文字か_である必要がある。isは引数を2つ取る組み込み述語。is/2というふうに書かれる。/2は引数を2つ取ることを意味する。is/2は英語でunificationを意味するらしい。式の最後にはピリオドが必要。また、同じことを表すのに次のように記述してもいい。isの左辺が変数の場合、isは中置演算子(infix operator)としての役割を持っているようだ。
?- A is 5 + 7. A = 12. ?- S is 5 - 7. S = -2. ?- M is 5 * 7. M = 35. ?- D is 5 / 7. D = 0.7142857142857143. ?-
ついでに2の平方根と半径3の円の面積も計算。累乗には^が使えることに感動。
?- is(Root, sqrt(2)). Root = 1.4142135623730951. ?- is(CircleArea, 3^2 * pi). CircleArea = 28.274333882308138. ?-
SWI-Prologの終了
SWI-Prologを終了するにはhalt/0という組み込み述語を使う。halt.と入力してエンターキーを押す。終わりのピリオドを忘れずに。
?- halt.
外部からファイルを読み込む
外部からファイルを読み込むのは簡単。Prologのソースコードをsource.plという名のファイルに保存しておいたとすると、次のようにする。
?- [source]. % source compiled 0.00 sec, 13 clauses true. ?-
ファイルの場所を示すパスも一緒に指定するときには一重引用符で挟む必要がある。/や.や-といった記号が含まれる場合はそうしないとエラーが生じてしまう。
?- ['/home/user/program/prolog/source']. % /home/user/program/prolog/source compiled 0.00 sec, 13 clauses true. ?-
consult/1という組み込み述語によってもソースファイルを読み込むことができる。
?- consult(source). % source compiled 0.00 sec, 13 clauses true. ?-
すでに読み込んだファイルを再編集した場合には、その更新内容を反映させるために組み込み述語のmake/0を使うことができる。
?- make. true. ?-
Correct to:
入力ミスをおかすとSWI-Prologは訂正すべきものを推定して示してくれる。例えば組み込み述語member/2をmembarとスペルミスをしてしまったら「memberが正しいんでしょう?」と問い返してくる。それが正しければyを押し、そうでなければnを押す。ちなみにyやnだけでyesやnoと補完くれる。
?- membar(c, [a, b, c]). Correct to: "member(c,[a,b,c])"? yes true. ?-
ヘルプ
help/1やapropos/1やexplain/1という述語を使うと何らかのヒントが得られるかもしれない。ただし英文。
?- help(member). true. ?-
?- explain(apropos). "apropos" is an atom Referenced from pui_manual->fill_dialog Referenced from 22-th clause of pce_principal:pce_lazy_send_method/3 online_help:apropos/1 is a predicate defined in /usr/lib/swi-prolog/library/help.pl:85 Possibly referenced from 2-th clause of online_help:apropos/1 true. ?- explain(^). "^" is an atom "^" is a infix (xfy) operator of priority 200 true. ?-
Prologでは英語の大文字で始まる変数に対して英語の小文字で始まるデータをatomと呼ぶようだ。predicate definedは定義済みの述語という意味。infix (xfy) operator of priority 200は優先順位200の中置演算子という意味。
未定義のプロシージャだというエラー
?-というプロンプトに対してまだ定義されていない述語を使ってルールや事実を新たに与えようとしたら、次のようなエラーメッセージが出てしまった。?-プロンプトが受け付けるのは、デレクティブと呼ばれる命令は除けばクエリと呼ばれる問い合わせだけらしい。
?- likes(a, b). ERROR: toplevel: Undefined procedure: likes/2 (DWIM could not correct goal) ?-
未定義の述語を定義しようとしたり事実やルールを新たに与えるためには、それをファイルに記述してそのソースファイルを[ファイル名].で読み込む必要があるようだ。edit/1という組み込み述語を使って独自のエディタを起動させることができるが、それは使い勝手が悪かった。読み込み済みのソースファイルに変更を加えた場合にはそれを反映させるためにmake.を実行する必要がある。
?- edit(likes). true. ?- make. true. ?-
別の方法もある。?-プロンプトに対して[user].と入力してエンターキーを2度ほど押すと|:というプロンプトが現れるので、そこで事実やルールの定義を行うことができる。そこから抜け出すにはCtrl+Dキーを押す。
?- [user]. |: likes(a, b). |: likes(b, c). |: % user://1 compiled 0.00 sec, 3 clauses true. ?- likes(a, b). true. ?- likes(a, c). false. ?-
こうしておけば引数を2つ持つ述語likes/2を?-プロンプトに対して用いることができるようになる。ちなみにlike(a, b)は「aはbを好む」という意味。
再び[user].を実行し、同じ述語によって新たな事実を加えようとすると次のような警告が出た。しかしそれは最初だけで、その後は問題なく動作した。
?- [user]. |: likes(b, a). Warning: user://2:23: Redefined static procedure likes/2 Previously defined at user://1:10 |: likes(a, e). |: likes(e, b). |: likes(c, d). |: % user://2 compiled 0.01 sec, 3 clauses true. ?- likes(e, b). true. ?-
Prologに触れたばかりなので、これらの記述には重大な誤りが含まれているかもしれない。
コメント
コメントを投稿