PrologのバックトラックとGUI
XPCEを使えばPrologで自由自在にGUIが使えるんですが、
そうすると、どうもプログラムがPrologっぽくなりません。
というのも、画面の表示を書き換えたり、
さらには変数の値を書き換えたりするので、
バックトラックを極力避けるような作りになるためです。
GUIとバックトラックをどうにか共存できないかと考えたところ、
マルチスレッドにする方法を思いつきました。
- 一つ目のスレッドがGUIを用いた入出力などを管理する。
- 二つ目のスレッドは通常のPrologのプログラムを走らせる。
- 二つのスレッドはメッセージ通信を行う。
この考えでどうにかならないかと思い試してみました。
走らせたプログラムはこんな感じです。
test :- (test1 ; thread_send_message(main, [println, 'No'])). test1 :- thread_self(S), thread_send_message(main, [println, 'member(X, [1,2,3,4,5])']), member(X, [1,2,3,4,5]), concat_atom(['X=', X], Text), thread_send_message(main, [println, Text]), thread_send_message(main, [click_wait, S]), check, thread_send_message(main, [println, 'Yes']). check :- thread_get_message(Msg), !, Msg == right.
member(X, [1,2,3,4])を行い、Xが適当な値に単一化されると
それを表示し(別のスレッドに アトムprintlnと共にthread_send_messageで送信しています)、
画面がクリックされるのを待ちます
(アトムclick_waitと自分のスレッドIDを送信すると、
画面がクリックされたときにアトムleftかrightが送信されるので、
それをthread_get_messageで受け取っています。)。
右クリックされると、画面にYesと表示して終了します。
左クリックされると、バックトラックが起こりmember(X, [1,2,3,4])が再び実行され、
Xが別の値に単一化されます。Xが単一化できなくなると、
画面にNoと表示して終了します。
……GUIとPrologっぽいのプログラムを共存させようと思ったんですが、
これをのPrologっぽいプログラムといっていいのやら。
けどまあ、とりあえず無事動いたので満足です。
もうすこし抽象化すれば見た目がマシになるかも。