This is my code in Prolog.
do(cinema):- parents(yes); (parents(no),weather(windy),money(less)).
do(play):- parents(no),weather(sunny).
do(stay):- parents(no),weather(rainy).
do(shopping):- parents(no),weather(windy),money(more).
start:- write('Parents: '),read(X),assert(parents(X)), write('Weather: '),read(Y),assert(weather(Y)), write('Money: '),read(Z),assert(money(Z)).
clear:- retract(parents(X));retract(weather(X));retract(money(X)).
I'm trying to accept data from user and then use decision tree to find out what task will be done.
I'm running the code as:
?-start, do(X).
But it does not write Weather after reading input for parents and keeps reading data.
There is nothing really wrong with your program. See http://swish.swi-prolog.org/p/JDAJcUhq.pl. The most likely cause is already mentioned: not finishing your term with a ".". clear/0 is indeed wrong, but not needed in the web version as each new query is executed in a fresh environment.
At least in SWI-Prolog there is no need to flush before a read operation from the terminal as flushing the console output streams is always done before the read.
Try putting some flush goals after the write goals and then remember to add a full stop on your input as you are using read/1 which wants a term.
Related
I am currently doing the Ruby on the Web project for The Odin Project. The goal is to implement a very basic webserver that parses and responds to GET or POST requests.
My solution uses IO#gets and IO#read(maxlen) together with the Content-Length Header attribute to do the parsing.
Other solution use IO#read_nonblock. I googled for it, but was quite confused with the documentation for it. It's often mentioned together with Kernel#select, which didn't really help either.
Can someone explain to me what the nonblock calls do differently than the normal ones, how they avoid blocking the thread of execution, and how they play together with the Kernel#select method?
explain to me what the nonblock calls do differently than the normal ones
The crucial difference in behavior is when there is no data available to read at call time, but not at EOF:
read_nonblock() raises an exception kind of IO::WaitReadable
normal read(length) waits until length bytes are read (or EOF)
how they avoid blocking the thread of execution
According to the documentation, #read_nonblock is using the read(2) system call after O_NONBLOCK is set for the underlying file descriptor.
how they play together with the Kernel#select method?
There's also IO.select. We can use it in this case to wait for availability of input data, so that a subsequent read_nonblock() won't cause an error. This is especially useful if there are multiple input streams, where it is not known from which stream data will arrive next and for which read() would have to be called.
In a blocking write you wait until bytes got written to a file, on the other hand a nonblocking write exits immediately. It means, that you can continue to execute your program, while operating system asynchronously writes data to a file. Then, when you want to write again, you use select to see whether the file is ready to accept next write.
I am running my code on SWI Prolog and Windows 7. In my code, I call another application using 'win_exec()' (I tried using the method 'shell()', but it won't work.), and at the end produces its output in a text file. However sometimes it runs for times like 30 minutes. Now my prolog code uses this output text file, to further parse it and process it.
This is the code I use to call the other application and then use its output file:
main(Value,X) :- win_exec('C:\\myfolder\\external_app.bat C:\\myfolder\\outputfile.txt', normal),
open('C:\\myfolder\\outputfile.txt', read, Mf),
read_file(Mf, X), % PROCEDURE TO READ FILE CONTENTS
close(Mf),
statistics(cputime, Value). % CALCULATE HOW LONG IT TOOK
However, since the file has not been outputted by that another application, it gives the error:
ERROR: open/4: source_sink `C:\myfolder\outputfile.txt' does not exist (No such file or directory)
So, as a workaround, I try to catch the error, handle it by comparing with 'existence_error' and then recursively call the open procedure, until it finally succeeds i.e. the other application has completed its processing and the output file is produced. This is my workaround code for this:
main(Value,X) :- win_exec('C:\\myfolder\\external_app.bat C:\\myfolder\\outputfile.txt', normal),
open_output(X), % PROCEDURE FOR FILE EXCEPTION HANDLING
statistics(cputime,Value).
open_output(X) :- catch((open('C:\\myfolder\\outputfile.txt', read, Mf), read_file(Mf,X), close(Mf)),
error(Err,Context),
open_output_aux(Err,X)). % AUX PROCEDURE TO RECOVER
% Write some code here
% open_output_aux code matches the error code with 'existence_error';
% if true, calls open_aux_wait procedure; else throw the error.
open_aux_wait(Z):- catch((open('C:\\myfolder\\outputfile.txt', read, Mf), read_file(Mf,Z), close(Mf)),
error(Err,Context),
open_aux_wait(Z)).
However this seems to be very inefficient of way doing this. I wanted to know if there's any better way to do this, like in java, you could simply call wait() while handling file exception. In the documentation, there's a method 'wait_for_input\3' but it says 'wait_for_input()' cannot be used for File Streams in Windows. I tried using it, but it gives error.
Any help or guidelines is greatly appreciated.
You have several options to solve this:
You can totally reconsider the way that these processes communicate. For example, SWI-Prolog ships with very powerful HTTP libraries, and you can set up the communication between the two processes to work over HTTP, using a client/server architecture. In this case, you avoid the busy waiting that currently uses many CPU cycles unnecessarily.
A much more trivial solution is to simply insert a call of the built-in sleep/1 predicate to put the process to sleep before trying to open the file again. Use for example sleep(1) to put the process to sleep for 1 second.
Use for example process_wait/2 to wait until the called process has finished and generated the file.
From what you are describing, it looks like (2) will do, (3) is slightly more elegant, and (1) may be good to know in general, for more difficult cases.
I would like to do the following :
I want to imple,ment the concept of FIFO in normal files using GUILE.
Two processes should communicate via a normal text file, that a third process , if needed, can access.
The subordinate of the original two processes should write in the file, line after line, that is append. So far so good. (implemented in c++)
The master proces however, should treat this file as a FIFO, it should read the first line, and do somethong corresponding to it, and delete the first line leaving the rest intact.
The problems are :
While the Master is accessing the file, the subordinate may come to a point where it must write there, leading to a conflict.
Popping the first line may need reading the whole ile out, in a string, poping the first thereof, and then saving it, which is memory intensive, and the second saving action may again conflict with the child trying to write there,
I wanted to implement this in GUILE, because since it is the official OS extension language, there might be better ways which addresses the above two issues.
But in the web I do not find much to orient myself. Please help, sorry for the lewss than concrete question, then I dont have a code snippet to show.
I'm writing an interpreter for a game. User enters its move to the interpreter and program executes that move.
Now I want to implement a time limit for each decision. Player shouldn't be able to think more than 30 seconds to write a move and press enter.
call_with_time_limit seemed relevant but it doesnt work properly as such:
call_with_time_limit( 30, read(X) ), Problem, write(Problem).
In this case, it waits for input, and when input is entered, timer starts afterwards. But I want the timer to start at the beginning.
How can I do it?
If you are interested in I/O related timeouts please consider wait_for_input/3 or set_stream/2. The built-in you found, call_with_time_limit/2 is not a simple and reliable interface.
Edit: I just see that you use read/1 for input. Please read in above documentation how to avoid blocking in read/1. It is not clear to me why you need this, but a user might simply enter Return, thereby circumventing the initial timeout. read/1 would now read that '\n' but then would wait for further input - without a timeout, while the user lavishly skims Wikipedia for the answer... might even ask the question on SO...
Your approach seems sensible: from the SWI-Prolog docs: 'Blocking I/O can be handled using the timeout option of read_term/3. '.
That's not really informative: changing timeout on user leads to some bug (I'll test more and will report to SWI_prolog mailing list if appropriate), even under catch/3.
The following seems to work
...,
current_input(I),
wait_for_input([I], A, 30),
...
If not input given (shorter time to test here...)
?- current_input(I), wait_for_input([I],A,5).
I = <stream>(0x7fa75bb31880),
A = [].
EDIT: the variable A will keep the list will contain the list of streams with ready input: I just reported the case where the user doesn't input anything before the timeout occurs. To get the actual input, using your supplied code:
tql :-
current_player(I),
writef('Its %d. players turn: ', [I]),
flush_output,
current_input(Input),
wait_for_input([Input], [Input], 5),
read(Input, Move),
writeln(Move).
current_player(1).
HTH
hey guys i have a question regarding amzi prolog with eclipse,
Im running a .pro file which executes a breadth first search and if queue gets too long,
the following error message appears:
system_error 1021 Control stack full.
Compile code or increase .cfg
parameter 'control'
If so, how may i run the compiled code under eclipse? I've tried running the project but the listener just ends without accepting any queries....?
Control stack full means one of two things:
You have a deep recursion that exhausts the control stack. In that case you need to increase the default value of 'control' in your amzi.cfg file. You may find you that have to increase 'heap', 'trail' and/or 'local' as well.
You have an error in your program causing an infinite recursion.
Running the program in the debugger will show you which case you've got. In the initial case you will see it digging deeper and deeper for a solution. In the later case you will see it chasing it's tail in circles with each recursion the same as the one before, but with different variables.
I don't know amzi prolog (I only used SICStus and SWI), and never used Eclipse for prolog, but as the error message says, try compiling (instead of consulting) your code. Look under project/properties for build configurations (like run/deug, as it works for Java/C++). Hopefully, that ".cfg paramerer" can also be accessed through project/properties.