从终端查询不打印任何内容

时间:2016-07-09 15:37:58

标签: command-line prolog swi-prolog

在命令行中运行时,这个

swipl -g "write(42)" -t "halt"

按预期打印42到STDOUT

但是,这个

swipl -g "X = 42" -t "halt"

不会打印任何内容,只会返回。

如何让它打印在REPL中打印的内容(即X = 42)?

注意:这是在Windows终端中。如果这实际上适用于Linux终端,请告诉我。

1 个答案:

答案 0 :(得分:5)

正如预期的那样,X = 42本身会产生无输出,因为(=)/2是一个完全纯粹的谓词,它本身不会产生任何副作用。这是Window,OSX和所有其他操作系统的情况。

即使有办法获取并重定向顶层输出本身,事实仍然是SWI顶层可能会发生变化,您不能依赖未来版本的行为方式与现在相同。从长远来看,你最好能够推出你自己的顶级,并准确地生成你想要的输出。

推出自己的顶级并不是那么难。诀窍主要是在阅读术语时使用variable_names/1选项,以便您可以跟踪要在答案中显示的变量名称。这是非常简单的开始:

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).

示例:

?- 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

很容易修改它,以便它适用于指定为参数的术语。

请注意,variable_names/1选项对于以这种方式阅读术语至关重要,并且由于ISO标准化工作,越来越多的实现为read_term/2和相关谓词提供了它。

这种读取变量名称的能力是实现便携式Prolog toplevel的要求

我留给您的主要练习是检查引用在所有情况下是否正确,以及(如果需要)产生答案,以便始终将它们粘贴在终奌站。要将此扩展为剩余的约束,请使用copy_term/3call_residue_vars/2来收集可以附加到绑定的待处理约束。