U S I N G P R O L O G ======================= ======================= This document is based on a previous document describing XSB Prolog, which in turn was based on (an earlier version of) http://www.cs.sunysb.edu/~sbprolog/xsb-page.html Getting Started with SWI-Prolog =============================== Invoking SWI-Prolog ------------------- SWI-Prolog can be invoked by the command: cslinux% swipl and you will find yourself in the top level interpreter. cslinux% swipl Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.6.63) Copyright (c) 1990-2008 University of Amsterdam. SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. Please visit http://www.swi-prolog.org for details. For help, use ?- help(Topic). or ?- apropos(Word). ?- Compiling SWI-Prolog programs ----------------------------- All source programs should be in files whose names have the suffix .pl. One of the ways to compile a program from a file in the current directory and load it into memory, is to type the query: [my_file]. where my_file.pl is the name of the file. You can also compile and load predicates input directly from the terminal by using the command: [user]. A CTRL-d or the atom end_of_file followed by a period terminates the input stream. Exiting SWI-Prolog ------------------ If you want to exit SWI-Prolog, issue the command halt., or simply type CTRL-d at the SWI-Prolog prompt. Getting help ------------ There is extensive built-in help. To get started, use the command: help. Debugging --------- SWI-Prolog allows you to trace through the execution of your code. (IMPORTANT: The tracing facility is VERY USEFUL !) Tracing ------- To turn on tracing, use trace. To turn tracing off, use notrace. When tracing is on, the system will print a message each time a predicate is: 1.initially entered (Call), 2.successfully returned from (Exit), 3.failed back into (Redo), and 4.completely failed out of (Fail). At each such event, a message is printed and the tracer stops and prompts for input. In addition to single-step tracing, the user can set spy points to influence how the tracing/debugging works. A spy point is set using spy/1. Spy points can be used to cause the system to enter the tracer when a particular predicate is entered. When the tracer prompts for input, the user may enter a return, or a single character followed by a return, with the following meanings: c, : Creep Causes the system to single-step to the next port (i.e. either the entry to a traced predicate called by the executed clause, or the success or failure exit from that clause). a: Abort Causes execution to abort and control to return to the top level interpreter. b: Break Calls the evaluable predicate break, thus invoking recursively a new incarnation of the system interpreter. The command prompt at break level n is [n] ?- The user may return to the previous break level by entering the system end-of-file character (e.g. ctrl-D). f: Fail Causes execution to fail, thus transferring control to the Fail port of the current execution. h: Help Displays the table of debugging options. l: Leap Causes the system to resume running the program, only stopping when a spy-point is reached or the program terminates. This allows the user to follow the execution at a higher level than exhaustive tracing. n: Nodebug Turns off debug mode. r: Retry (fail) Transfers to the Call port of the current goal. Note, however, that side effects, such as database modifications etc., are not undone. s: Skip Causes tracing to be turned off for the entire execution of the procedure. Thus, nothing is seen until control comes back to that procedure, either at the Success or the Failure port. e: Exit Causes immediate exit from SWI-Prolog back to the operating system. Other Debugging Predicates -------------------------- debug Turns on debugging mode. This causes subsequent execution of predicates with trace or spy points to be traced. The predicates trace/1 and spy/1 cause debugging mode to be turned on automatically. nodebug Turns off debugging mode. This causes trace and spy points to be ignored. Examples -------- Here are some very simple old functions of mine. Note that comments in Prolog begin with a %. % within(+ Variable, + VarList) % % Test whether Variable is in VarList. within(_,[]):-fail. within(Var,[HeadOne|_]):- Var==HeadOne. within(Var,[_|VarList]):- within(Var,VarList). % nth(+Number, +ListOfElements, -Element) % % Element is the Number-th element in the list ListOfElements. nth(N, List, Element):- N1 is N - 1, length(Head, N1), append(Head, [Element|_Rest], List). I stored them in the file test2.pl Now, I had the following session. The examples are self-explanatory. For that, keep the above subsection on "trace" in mind. As you see in the examples below, your variables X, Y, Z, ... are replaced by internaly generated variables _G338, _G341, _G344, ... . This does not matter for you to follow the computation of your program; just do a mapping from your original variables in the new ones to grasp what is going on. ?- [test2]. % test2 compiled 0.00 sec, 2,072 bytes true. ?- trace. %%%% Here I am invoking trace/0. Unknown message: query(yes) [trace] ?- within("X",[Y,Z,T,V,X,P]). Call: (7) within([88], [_G338, _G341, _G344, _G347, _G350, _G353]) ? creep Call: (8) [88]==_G338 ? creep Fail: (8) [88]==_G338 ? creep Redo: (7) within([88], [_G338, _G341, _G344, _G347, _G350, _G353]) ? creep Call: (8) within([88], [_G341, _G344, _G347, _G350, _G353]) ? creep Call: (9) [88]==_G341 ? creep Fail: (9) [88]==_G341 ? creep Redo: (8) within([88], [_G341, _G344, _G347, _G350, _G353]) ? creep Call: (9) within([88], [_G344, _G347, _G350, _G353]) ? creep Call: (10) [88]==_G344 ? creep Fail: (10) [88]==_G344 ? creep Redo: (9) within([88], [_G344, _G347, _G350, _G353]) ? creep Call: (10) within([88], [_G347, _G350, _G353]) ? creep Call: (11) [88]==_G347 ? creep Fail: (11) [88]==_G347 ? creep Redo: (10) within([88], [_G347, _G350, _G353]) ? creep Call: (11) within([88], [_G350, _G353]) ? creep Call: (12) [88]==_G350 ? creep Fail: (12) [88]==_G350 ? creep Redo: (11) within([88], [_G350, _G353]) ? creep Call: (12) within([88], [_G353]) ? creep Call: (13) [88]==_G353 ? creep Fail: (13) [88]==_G353 ? creep Redo: (12) within([88], [_G353]) ? creep Call: (13) within([88], []) ? creep Call: (14) fail ? creep Fail: (14) fail ? creep Redo: (13) within([88], []) ? creep Fail: (13) within([88], []) ? creep false. [debug] ?- trace. Unknown message: query(yes) [trace] ?- within("X",[Y,Z,T,V,X,P]). Call: (7) within([88], [_G635, _G638, _G641, _G644, _G647, _G650]) ? skip false. [debug] ?- trace. Unknown message: query(yes) [trace] ?- within(X,[Y,Z,T,V,X,P]). Call: (7) within(_G644, [_G632, _G635, _G638, _G641, _G644, _G647]) ? creep Call: (8) _G644==_G632 ? creep Fail: (8) _G644==_G632 ? abort % Execution Aborted ?- within(X,[Y,Z,T,V,X,P]). true . ?- within(X,[Y,Z,T,V,X,P]). true . ?- trace. Unknown message: query(yes) [trace] ?- within(X,[Y,Z,T,V,X,P]). Call: (8) within(_G350, [_G338, _G341, _G344, _G347, _G350, _G353]) ? creep Call: (9) _G350==_G338 ? Options: +: spy -: no spy /c|e|r|f|u|a goal: find .: repeat find a: abort A: alternatives b: break c (ret, space): creep [depth] d: depth e: exit f: fail [ndepth] g: goals (backtrace) h (?): help i: ignore l: leap L: listing n: no debug p: print r: retry s: skip u: up w: write m: exception details C: toggle show context Call: (9) _G350==_G338 ? skip Fail: (9) _G350==_G338 ? skip Redo: (8) within(_G350, [_G338, _G341, _G344, _G347, _G350, _G353]) ? skip Exit: (8) within(_G350, [_G338, _G341, _G344, _G347, _G350, _G353]) ? leap true . [debug] ?- nodebug. %%%% Here I exit from debug. true.