You will be running SICStus Prolog on the undergraduate SUN servers. The preferred way to run Prolog is from within emacs, as then your output is in an emacs window, which can be manipulated as text.
Use a two window (i.e., buffer) emacs environment, which encourages an interactive style of editing and running Prolog programs. The upper window is used primarily for editing of facts and rules. The lower window (which is running the shell) is used for executing programs; it keeps a running record of your execution. Thus, you can save the results of a Prolog session by saving this lower window using the usual emacs file saving commands (e.g., Control-x Control-w).
After you execute this command, you type into the emacs buffer exactly as you would at the system level. After you end the Prolog session by typing ?- halt., you can save your output buffer to a file.
We expect you to run as follows:
Infinite loops in Prolog programs, usually caused by poorly written recursive rules (e.g., a base case entered *after* the recursive rule, or a leftmost recursive subgoal on the rhs of a rule), are easy to notice: if the interpreter produces no output to the screen for a while, your program is probably in an infinite loop. When running Prolog, Control-c Control-c (yes, it's two of them) interrupts execution and results in the Prolog prompt for help. If you reply to the prompt h, thus asking for help, these are some of the choices open to you:
spy(). -- causes a trace of the execution of the specified clause only. During execution, once that clause is reached, the trace is presented and several options are possible:
Return -- single step trace
l -- leap trace (allows you to skip over subgoals)
? -- help
g -- shows the ancestor list of current goals not yet satisfied
The following program was run on remus and traced as shown below, to give you an idea of what the trace output means. The annotations which follow the % on the right, as well as the indentation were inserted after the run of the program. Note that Head [j->k] p(...) indicates that the j-th rule for predicate p is being tried currently, and then the k-th rule will be tried next. Head [j] p(...) means there are no more rules to try for p.
diff(X,Y) :- \+(X=Y). mem(A,[A|B]). %rule1 finds element as head of list mem(A,[C|X]) :- diff(A,C), mem(A,X). %rule2 continues to look for A in listOutput obtained in emacs:
| ?- [mem]. {consulting /ug/s7/www/Public/cs314/f2002/projs/prolog/mem.pl...} {Warning: [B] - singleton variables in mem/2 in lines 2-3} {/ug/s7/www/Public/cs314/f2002/projs/prolog/mem.pl consulted, 0 msec -104 bytes} yes {trace} | ?- mem(a,[b,a]). 1 1 Call: mem(a,[b,a]) ? %try rule2 on [b,a] 2 2 Call: diff(a,b) ? 3 3 Call: a=b ? 3 3 Fail: a=b ? %diff fails 2 2 Exit: diff(a,b) ? 3 2 Call: mem(a,[a]) ? %try rule2 on [a] ? 3 2 Exit: mem(a,[a]) ? ? 1 1 Exit: mem(a,[b,a]) ? yes {trace} | ?- mem(a,[b,c]). 1 1 Call: mem(a,[b,c]) ? 2 2 Call: diff(a,b) ? %try rule2 on [b,c] 3 3 Call: a=b ? 3 3 Fail: a=b ? 2 2 Exit: diff(a,b) ? 3 2 Call: mem(a,[c]) ? %try rule2 on [c] 4 3 Call: diff(a,c) ? 5 4 Call: a=c ? 5 4 Fail: a=c ? 4 3 Exit: diff(a,c) ? 5 3 Call: mem(a,[]) ? %try rule2 on [] 5 3 Fail: mem(a,[]) ? 3 2 Fail: mem(a,[c]) ? 1 1 Fail: mem(a,[b,c]) ? %no more choices no {trace} | ?- mem(a,[a]),fail. 1 1 Call: mem(a,[a]) ? %try rule1 on [a] ? 1 1 Exit: mem(a,[a]) ? %rule1 succeeds 1 1 Redo: mem(a,[a]) ? %fail forces a retry on rule1 %which means try rule2. 2 2 Call: diff(a,a) ? 3 3 Call: a=a ? 3 3 Exit: a=a ? 2 2 Fail: diff(a,a) ? %rule2 fails 1 1 Fail: mem(a,[a]) ? no %no more answers {trace} | ?- Prolog interruption (h for help)? e Process prolog finished