I would like to read a term from a (socket) stream (using some user-defined operators) but I don't want to get stuck waiting for the term to be completed (i.e. reaching the "." at the end). E.g., one line should be read from the stream, and if that line doesn't contain a complete term I would like the action to fail (and not pend).
Can I read one line as a list of characters and then convert them to a term? How? The string2term does not seem to do the job.
As mentioned in the documentation for string2term the way to do this is to be able to call the full reader on a string. The general solution is to modify Ciao so that we are able to treat strings in memory as any other stream, so that one just 'opens' the string, gets a stream identifier back and reads from that string. This is something that was planned for 1.6 but alas didn't make it (it is not very difficult --quite frankly, we had in mind and forgot about it).
The current implementation of string2term is a temporary kludge: a simple parser in Prolog which works provided there are no operator declarations:
Ciao-Prolog 1.7 #0: Mon Jul 17 16:38:11 CEST 2000 ?- use_module(library(atom2term)).
yes ?- string2term("f(a)",X).
X = f(a) ?
yes ?-
In case it is useful for you, I am adding at the end another version of string2term.pl that creates a temporary file. This one at least understands the standard operators. If you want other operators to be active when parsing, a solution is to add code which includes the corresponding op declarations in the temporary file.
Hope this helps...
P.S. If someone out there wants to make the fix I mentioned above to the sources and send the patch it would save us a little time...
The version of string2term using a temporary file:
:- module(string2term,[string2term/2]).
:- include(library(assertions)). :- use_module(library(dec10_io)). :- use_module(library(strings)). :- use_module(library(messages),[error_message/2,debug_message/2]). :- use_module(library(system), [delete_file/1, mktemp/2, file_exists/1]).
:- comment(module,"A very simple implementation of string to term using a temporary file to write the string into and read the term from.").
%% Urrgh, we need to change this... temp_file(File):- mktemp('/tmp/sqlresponseXXXXXX',File).
string2term(String,Term):- temp_file(File), telling(OldO), tell(File), debug_message( "Ready to write in the File ~w the string ~s",[File,String]), write_string(String), write_string(".\n"), told, debug_message("Closing the file ~w",[File]), tell(OldO), seeing(OldI), see(File), do_the_read(String,OldI,Term,File).
do_the_read(_String,OldI,Term,File) :- debug_message("About to read term into ~w~n", [Term]), read(Term), debug_message("Term read~n", []), seen, see(OldI), debug_message("Closing and restoring IO~n", []), !, delete_file_aux(File). do_the_read(String,OldI,_Term,File) :- delete_file_aux(File), error_message("could not convert string ~s",[String]), seen, see(OldI), fail.
delete_file_aux(File):- file_exists(File), !, delete_file(File). delete_file_aux(_). % ---------------------------------------------------------------------------- :- comment(version_maintenance,on).
:- comment(version(0*1+2,1998/11/18,14:10*09+'MET'), "Updated calls to predicates in @lib{messages} library to use new names. (Ignacio Caballero Blanco)").
:- comment(version(0*1+1,1998/06/22,19:00*40+'MET DST'), "Moved tmp file to /tmp. Still a serious kludge, though. Therefore, versions kept local until we write a real read_from_string. (Manuel Hermenegildo)").
:- comment(version(0*1+0,1998/06/08,19:22*43+'MET DST'), "A very simple implementation of string to term using a temporary file to write the string into and read the term from. (Ignacio Caballero Blanco)").
% ----------------------------------------------------------------------------