9. PROLOG I/O • I/O and the relational model. • PROLOG I/O operators. – Not really predicates. • I/O with characters. • I/O with terms. • I/O with lists. • I/O with files. • Turning lists of characters into atoms. 9.1 I//O And The Relational Model • I/O does not fit into the relational model of computation. – I/O cannot be backtracked. – Theoretically could backtrack over input. Very inefficient though. – Cannot backtrack output. What’s said is said. • PROLOG provides I/O operators as an “add on”. • PROLOG I/O operators are not really predicates. 9.2 PROLOG I/O Operators • PROLOG handles I/O via constructs which are essentially C++/Java style statements : • get0(Ch) – Next input character = Ch. • get(Ch) – Next valid input character = Ch. – A valid input character is any printable character except spaces, tabs and end of line characters. • put(Ch) – Next output character = Ch. • PROLOG treats characters as ordinal numbers (i.e. as ASCII/Unicode numbers). – The arguments of get0, get and put must be numbers, not characters. 9.3 PROLOG I/O Operators II • nl – Next output character = end of line. • read(X) – Next input term = X. • write(X) – Next output term = X. • Note that = means match. • get0, get, put, nl, read and write cannot be backtracked in the usual way. – GNU PROLOG will backtrack over them but it cannot undo the I/O. – Some PROLOGs will not backtrack over them at all. 9.4 I/O With Characters • Reading a single character : | ?- get0(Ch). a Ch = 97 yes | ?- • Matching a single character : | ?- get0(97). a yes | ?- • A common mistake (‘9’ has ASCII code 57) : | ?- get0(97). 97 no | ?- 9.5 I/O With Characters II • Using ; (logical or) : | ?| ?yes | ?| ?yes | ?- get0(Ch) ; true. q get0(97) ; get0(97). qa • First query works because of the true. Second query works because the second input character is ‘a’. • get is identical to get0 except that it ignores all non-printable characters, spaces, tabs and end of line characters. 9.6 I/O With Characters III • put takes a numeric argument and prints the corresponding character. | ?- put(97). a yes | ?- put(X). uncaught exception ... | ?- X is 90 + 10, put(X). d | ?- put(97), nl, put(100). a d yes | ?- • put requires its argument to be instantiated. – Same as the other arithmetic operators. 9.7 I/O With Terms • PROLOG will input and output whole terms : | ?- read(X), read(Y). | ?- p(1,2). q(jim,joe). X = p(1,2) Y = q(jim,joe) yes | ?- write(q(a,b,c)), write(p(1,2,3)). q(a,b,c)p(1,2,3) yes | ?- X = 1, Y = 2, write(p(X,Y)). p(1,2) X = 1 Y = 2 yes | ?9.8 I/O With Lists • Read characters up to a ‘.’ and compute a checksum : checkSum(Chs, N) :get0(Ch), (Ch = 46, % . character Chs = [], N = 0 ; checkSum(NewChs, NewN), Chs = [Ch | NewChs], N is Ch + NewN ). | ?- checkSum(L, R). hello world. L = [104, ... 100] R = 1116 | ?- 9.9 I/O With Lists II • Using get : checkSum2(Chs, N) :get(Ch), (Ch = 46, % . character Chs = [], N = 0 ; checkSum2(NewChs, NewN), Chs = [Ch | NewChs], N is Ch + NewN ). | ?- checkSum2(L, R). hello world. L = [104, ... 100] R = 1084 | ?9.10 I/O With Lists III • Printing a list of terms : printList([]). printList([T | Ts]) :write(T), nl, printList(Ts). | ?- printList([hello, world]). hello world yes | ?- 9.11 I/O With Files • PROLOG reads input from the standard input stream. – Normally connected to the keyboard. • PROLOG writes output to the standard output stream. – Normally connected to the screen. • The standard I/O streams can be redirected to files. • see(fileName) : Connect input stream to file fileName. • seen : Disconnect the input stream. • tell(fileName) : Connect the output stream to file fileName. • told : Disconnect the output stream. • Similar mechanism to open and close in C++. – Voodoo in Java. 9.12 I/O With Files II • see, seen, tell and told cannot be (properly) backtracked over. – GNU PROLOG backtracks over them but does not undo their effect on the file system. – Some PROLOGs will refuse to backtrack over them at all. • Logical variables can be used as arguments to see and tell. – Arguments must be valid terms. • The filename user means the keyboard or screen. – see(user) : connect the input stream to the keyboard. – tell(user) : connect the output stream to the screen. 9.13 Copying A File copyFile :read(InFileName), read(OutFileName), see(InFileName), tell(OutFileName), echo, seen, told, see(user), tell(user). echo :get0(Ch), (Ch = -1, ; put(Ch), echo ). 9.14 Copying A File II • Most PROLOGs connect back to the standard streams after seen and told but it is safest not to rely on it. • Not all PROLOGs return ASCII -1 when reading from an empty file. | ?- copyFile. temp. temp1. true ? (10 ms) yes | ?- • The query succeeds and as a side effect copies the contents of the file temp to the file temp1. 9.15 Echoing The Keyboard To The Screen • Could use echo on the standard I/O streams : | ?- echo. sljdkljhsdfljhsdf sljdkljhsdfljhsdf 30457305703785rwpwirnpfwpfhpwf 30457305703785rwpwirnpfwpfhpwf <CTRL-D> true ? ; uncaught exception ... | ?- • Must use <CTRL-D> to send the end of file character. • If we force a backtrack GNU PROLOG gives an error message. – Don’t try to backtrack I/O operations. 9.16 Turning Lists Of Characters Into Atoms • name(A, Str) – Succeeds if the atom A matches with the contents of the string Str. • To PROLOG a string is a list of ASCII numbers. – Goal succeeds if Str is the list of ASCII numbers of the characters which make up A. | ?- name(fred, Str). Str = [102,114,101,100] | ?- name(X,[102,114,101,100]) X = fred. | ?- • name is most useful for converting text read from input into atoms. – Particularly useful with assert. 9.17 Turning Lists Of Characters Into Atoms II • readAtom reads a string of characters from input and converts it into an atom. – The string is terminated by the ‘.’ character (ASCII 46). readAtom(A) :readStr(Str), name(A,Str). readStr(Str) :get0(Ch), (Ch = 46, Str = [] ; readStr(NewStr), Str = [Ch | NewStr] ). 9.18 Turning Lists Of Characters Into Atoms III | ?- readAtom(A). fred. A = fred ? yes | ?- readAtom(A), assertz(word(A)). fred. A = fred ? yes | ?- word(X). X = fred yes | ?- readAtom(A). a123->>>--<<<<102949 aqa. A = ‘a123->>>--<<<<102949 aqa’ yes | ?- read(A). a123->>>--<<<<102949 aqa. uncaught exception .... | ?- • readAtom is more powerful than PROLOG’s read. 9.19 Summary • I/O is an “add on” to PROLOG. – Not relational. – PROLOG cannot undo I/O operations on backtracking. • get0(Ch) : Next input character = Ch. • get(Ch) : Next valid input character = Ch. • put(Ch) : Next output character = Ch. • PROLOG treats characters as ASCII/Unicode numbers. • nl : Next output character = end of line. • read(X) : Next input term = X. • write(X) : Next output term = X. 9.20 Summary II • PROLOG reads input from the standard input stream. • PROLOG writes output to the standard output stream. • see(fileName) : Connect input stream to file filename. • seen : Disconnect input stream from file filename. • tell(fileName) : Connect output stream to file filename. • told : Disconnect output stream from file filename. • Filename user means keyboard / screen. • name(A, Str) : Succeeds if A matches with the string Str. – Can use name to convert strings into atoms. – Particularly useful with asserta and assertz. 9.21