nptclのブログ

Common Lisp処理系nptの開発メモです。https://github.com/nptcl/npt

nptでPrologを使う

Prologを使いたいのですがどうしたらいいのか。
ちょっと調べてみると、Common Lispで動作するPrologがあるらしく、 有名どころではPAIPROLOGというものがありました。

これはPAIPという有名な本に載っていたものなんだと思います。
自分は見たことが無いので詳しく調べることができません。
今は金が無さ過ぎて食費すらない状態なので買うのは無理ですが、 そのうち余裕ができたら買ってみたいとは思います。

ソースは次の所から入手できます。

https://github.com/quek/paiprolog

READMEを読むと、元々はcl-user.netというサイトにあったものを forkして登録したそうです。
さっそくcl-user.netに接続してみると、 ひどい事にロシア語のエロサイトが表示されました。
なんだそれ。
みなさんも注意してください。
こういう所で、Common Lisp自体がとても古いものなんだなと思わされます。
昔はちゃんとしたLispのサイトだったんでしょうけど、 どういう経緯かドメインがエロサイト経営者の手に渡って そこへリダイレクトされるようになったんでしょうね。
Common Lispの旬はとっくに過ぎているということなのでしょう。
でもまあ自分はまだまだ使いますけど。

それはいいとして、PAIPROLOGをnptで動かせたら、 CコンパイラだけでPrologが使えるんじゃないか? と思いました。
本来のPAIPROLOGのインストールはこんな感じらしいです。

(ql:quickload "paiprolog")

でもnptにはasdfやらquicklispやらが無いので、 paiprolog.asdに記載されているファイルを手動で読み込むしかありません。

ロード用のファイルload.lispを作成しましょう。
こんな感じ。

;; load.lisp
(load #p"package.lisp")
(load #p"auxfns.lisp")
(load #p"patmatch.lisp")
(load #p"unify.lisp")
(load #p"prolog.lisp")
(load #p"prologc.lisp")
(load #p"prologcp.lisp")
(load #p"prolog-ext.lisp")

これを読み込むとどうなるか。

$ npt --load load.lisp
-> エラー

全然ダメ。
nptのバグなので修正してから再チャレンジ。

確認として以下のルールを動かしてみます。

append([], X, X).
append([U|X], Y, [U|Z]) :- append(X, Y, Z)

実行は下記の通り。

$ npt --load load.lisp
WARNING: Unused variable CONT.
WARNING: Unused variable CONT.
WARNING: Unused variable ?LIST.
WARNING: Unused variable ?TERM.
WARNING: Unused variable CONT.
WARNING: Unused variable ?PI.
WARNING: Unused variable CONT.
WARNING: Unused variable ?PI.
WARNING: Unused variable ?OPTIONS.
WARNING: Unused variable CONT.
WARNING: Unused variable CONT.
WARNING: Unused variable ?STREAM-OR-ALIAS.
WARNING: Unused variable S.
* (defpackage work (:use cl paiprolog))
#<PACKAGE WORK>
* (in-package work)
#<PACKAGE WORK>
* (<-- (append () ?x ?x))
APPEND
* (<- (append (?u . ?x) ?y (?u . ?z))
      (append ?x ?y ?z))
APPEND
*

ルールを登録したのでテストしてみます。

* (prolog
    (append ?x ?y (a b c d e))
    (lisp (format t "~A - ~A~%" ?x ?y)))
WARNING: This implementation cannot compile a function.
WARNING: This implementation cannot compile a function.
NIL - (A B C D E)
(A) - (B C D E)
(A B) - (C D E)
(A B C) - (D E)
(A B C D) - (E)
(A B C D E) - NIL
NIL
*

何となくうまく行っていますね。
どこまでちゃんと動くんだろう?
まだ使い方がわからないのでこんなことしかできませんが、 なんか嬉しいです。

これで手軽にPrologが使える!
という訳なのかというと正直微妙だと思います。
第一にnpt経由なので絶対遅い。
第二にCコンパイラだけで構築できるPrologというのは わざわざnptを使わんでもすでに色々と存在するのでは?
さらにPAIPROLOGのライセンスはnptと違って 好きに扱っていいものでは無いと思います。

でも個人的には色々と使ってみたい。
Prologって興味はあるものの全然知らないんですよね。
自分としてはとても身近になったように思えます。