问题
When ran in the command line, this
swipl -g "write(42)" -t "halt"
prints 42 to STDOUT
as expected.
However, this
swipl -g "X = 42" -t "halt"
does not print anything, it simply returns.
How do I get it to print what it prints in the REPL (that is, X = 42
)?
Note: this is in a Windows terminal. Let me know if this actually works in a Linux terminal.
回答1:
As expected, X = 42
by itself produces no output whatsoever, because (=)/2
is a completely pure predicate that does not yield any side effects by itself. This is the case on Window, OSX and all other operating systems.
Even if there were a way to obtain and redirect the toplevel output itself, the fact remains that the SWI toplevel is subject to change and you cannot rely on future versions to behave in the same way as it does now. Long term, you will likely be better off to roll your own toplevel and produce exactly the output you want.
It is not so hard to roll your own toplevel. The trick is mainly to use the variable_names/1
option when reading terms, so that you can keep track of the variable names that you want to show in answers. Here is a very simplistic start:
repl :- read_line_to_codes(current_input, Codes), read_term_from_codes(Codes, Term, [variable_names(NameVars)]), call(Term), report_bindings(NameVars). repl :- repl. report_bindings(NameVars) :- phrase(bindings(NameVars), Bs), format("~s", [Bs]). bindings([]) --> []. bindings([E]) --> name_var(E). bindings([E1,E2|Rest]) --> name_var(E1), ",\n", bindings([E2|Rest]). name_var(Name=Var) --> format_("~w = ~q", [Name,Var]). format_(Format, Ls) --> call(format_codes(Format, Ls)). format_codes(Format, Ls, Cs0, Cs) :- format(codes(Cs0,Cs), Format, Ls).
Example:
?- repl. |: X = 4, between(1, 3, Y). X = 4, Y = 1 true ; X = 4, Y = 2 true ; X = 4, Y = 3 true ; |: X = 7. X = 7
It is easy to modify this so that it works on terms that are specified as arguments.
Note that the variable_names/1
option is essential for reading terms in such a way, and thanks to the ISO standardization effort an increasing number of implementations provide it for read_term/2
and related predicates.
This ability to read variable names is a requirement for implementing a portable Prolog toplevel!
The main exercise that I leave for you is to check if the quoting is right in all cases and (if desired) to produce answers in such a way that they can always be pasted back on the terminal. To extend this to residual constraints, use copy_term/3
and call_residue_vars/2
to collect pending constraints that you can append to the bindings.
来源:https://stackoverflow.com/questions/38283454/querying-from-the-terminal-doesnt-print-anything