40.5.2 Prolog The Master, Tk The Slave

The second approach is to have Prolog be the master and Tk the slave. This is suitable when heavy processing is done in the Prolog code and Tk is used mostly to display the state of the computation in some way rather than as a traditional GUI; i.e. during computation Prolog often makes calls to Tk to show some state, but the user rarely interacts with the application.

In our Prolog+Tcl/Tk setting this involves the following steps:

Again it its purest form, Prolog makes calls to Tcl, but Tcl does not make calls to Prolog. The result of a call to Tcl is either passed back through the Result variable of a tcl_eval/3 call.

A good example of this is the Tcl/Tk display for our 8-queens problem, that we saw earlier; see Queens Display.

We will now fill out the example by presenting the Prolog master part. The Prolog program calculates a solution to the 8-queens problem and then makes calls Tcl/Tk to display the solution. In this way Tcl/Tk is the slave, just being used as a simple display.

We have already seen the Tcl/Tk part, but here is the Prolog part for generating a solution and displaying it:

     :- use_module(library(tcltk)).
     :- use_module(library(lists)).
     
     go :-
         tk_new([name('SICStus+Tcl/Tk - Queens')], Tcl),
         tcl_eval(Tcl, 'source queens.tcl', _),
         tk_next_event(Tcl, Event),
         queens(8, Qs),
         reverse(L, LR),
         tcl_eval(Tcl, [show_solution, br(LR)], _),
         fail.
     go.
     
     queens(N, Qs) :-
         range(1, N, Ns),
         queens(Ns, [], Qs).
     
     queens(UnplacedQs, SafeQs, Qs) :-
         select(Q, UnplacedQs, UnplacedQs1),
         \+ attack(Q, SafeQs),
         queens(UnplacedQs1, [Q|SafeQs], Qs).
         queens([], Qs, Qs).
     
     attack(X, Xs) :- attack(X, 1, Xs).
     
     attack(X, N, [Y|_Ys]) :- X is Y + N.
     attack(X, N, [Y|_Ys]) :- X is Y - N.
     attack(X, N, [_Y|Ys]) :-
         N1 is N + 1,
     attack(X, N1, Ys).
     
     range(M, N, [M|Ns]) :-
         M < N,
         M1 is M + 1,
         range(M1, N, Ns).
     range(N, N, [N]).
     
     :- go.

All this simply does it to create a Tcl/Tk interpreter, load the Tcl code for displaying queens into it, generate a solution to the 8-queens problem as a list of integers, and then calls show_solution/2 in the Tcl interpreter to display the solution. At the end of first clause for go/0 is a fail clause that turns go/0 into a failure driven loop. The result of this is that the program will calculate all the solutions to the 8-queens problem, displaying them rapidly one after the other, until there are none left.