Querying from the terminal doesn't print anything

半城伤御伤魂 提交于 2019-12-23 13:02:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!