%A simple read predicate. %The user enters a term, followed by a period (and then a newline). %It prints the selection out, and returns to the beginning. %It only stops when the user enters 'quit.' simpleread:- write('Type \'quit.\' to finish; any other single word to display'),nl, repeat, read(X), write(X), nl, X=quit,!. %If the user typed anything other than 'quit.', then the 'X=quit' subgoal fails, %forcing it to backtrack to the previous branch-point (in this case, the 'repeat' line). %This predicate reads a single line. The rest of the input file will remain %unread, and unacknowledged. It's okay to feel sad for it. readoneline:- current_input(OldStream), see('inputfile.txt'), seeing(NewStream), read_line_to_codes(NewStream,ASCIIList), name(Line,ASCIIList), write(Line),nl, see(OldStream). %This predicate, on the other hand, reads ALL the lines! %Broom not included. readALLthelines:- current_input(OldStream), see('inputfile.txt'), seeing(NewStream), repeat, %Note that we put the 'repeat' after we've opened and identified our stream! read_line_to_codes(NewStream,ASCIIList), name(Line,ASCIIList), write(Line),nl, %This is the end of the current read. We need to control our loop after this line! %something clever could go here. see(OldStream). %Try it out! %... have you tried it yet? You did? %You see what I did there? Doesn't work, does it? It either reads a single line, or if you %keep hitting semicolon, it eventually fails! %So then, what's the problem? %Actually, there are two, but they're related: %1. A 'repeat' loop only actually repeats if something after the 'repeat' line fails. %2. We aren't considering how to handle the end of the file! %(Remember that 'name' expects to get a list of numbers, not a single element) readALLthelinesTotally:- current_input(OldStream), see('inputfile.txt'), seeing(NewStream), repeat, %Note that we put the 'repeat' after we've opened and identified our stream! read_line_to_codes(NewStream,ASCIIList), name(Line,ASCIIList), write(Line),nl, %This is the end of the current read. We need to control our loop after this line! fail, see(OldStream). %Did you try it out? Ha! Tricked you again! %However, notice that we're closer now. We have it successfully looping through all %of the data. Now we just need to properly test for EOF. %read_line_to_codes returns end_of_file instead of a list when at the EOF, so it's easy! readALLthelinesForReal:- current_input(OldStream), see('inputfile.txt'), seeing(NewStream), repeat, %Note that we put the 'repeat' after we've opened and identified our stream! read_line_to_codes(NewStream,ASCIIList), (ASCIIList=end_of_file->true;(name(Line,ASCIIList),write(Line),nl,fail)), seen, see(OldStream),!. %Now, just for ha-ha's, let's say we had more work to do than simply reconstructing %the string from the ASCII list? That could be... ugly. %So let's get overly picky, shall we? readALLthelinesnicely:- current_input(OldStream), see('inputfile.txt'), seeing(NewStream), repeat, %Note that we put the 'repeat' after we've opened and identified our stream! read_line_to_codes(NewStream,ASCIIList), (ASCIIList=end_of_file->true;process_data(ASCIIList) /*fail could be here instead*/), seen, see(OldStream),!. process_data(ASCII):- name(Message,ASCII), write(Message),nl, assert(wisdom(Message)), !, %This cut is likely overly cautious fail. %This fail could also be handled right after process_data is invoked.