PrologのバックトラックとGUI

XPCEを使えばPrologで自由自在にGUIが使えるんですが、
そうすると、どうもプログラムがPrologっぽくなりません。
というのも、画面の表示を書き換えたり、
さらには変数の値を書き換えたりするので、
バックトラックを極力避けるような作りになるためです。
GUIとバックトラックをどうにか共存できないかと考えたところ、
マルチスレッドにする方法を思いつきました。

  • 一つ目のスレッドがGUIを用いた入出力などを管理する。
  • 二つ目のスレッドは通常のPrologのプログラムを走らせる。
  • 二つのスレッドはメッセージ通信を行う。

この考えでどうにかならないかと思い試してみました。
XPCE
走らせたプログラムはこんな感じです。

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っぽいプログラムといっていいのやら。
けどまあ、とりあえず無事動いたので満足です。
もうすこし抽象化すれば見た目がマシになるかも。

Leave a Reply