如何让 SWI-Prolog 在交互模式下始终打印带引号的字符串

How to get SWI-Prolog to always print strings with quotes, in interactive mode

当使用SWI-prolog时,它会打印不需要引号的输出(output that doesn't contain special characters),不带引号。 例如:

?- p('this_is_a_string').
true.

?- p(X).
X = this_is_a_string.

我希望 Prolog 的输出始终带有引号。如果我的输出最终引用了函子名称之类的东西,那也没关系,这些东西最初在输入时并没有被引用。我怎样才能做到这一点?

要更改 SWI-Prolog 顶层输出的默认行为,您需要查看 setting a flag。如果您查询适当的标志,您应该会发现这是您的默认输出:

?- current_prolog_flag(print_write_options, Options).
Options = [portray('true'), quoted('true'), numbervars('true')]. 

在这种特殊情况下,已经设置了所需的标志:我们的 Options.

中有 portray('true')

portray/1 是一个可以断言的动态谓词。打印的时候会调用一个ground term,如果成功就认为这个term已经打印出来了。

因此,在您的情况下,您可以断言以下内容:

portray(Term) :- atom(Term), format("'~s'", Term).

现在您将获得所需的行为:

?- p(this_is_an_atom).
true.

?- p(X).
X = 'this_is_an_atom'.

如果您一直需要它,您可以将它添加到您的 .swiplrc 文件中。请注意,这对 write/1 和类似谓词没有影响,您需要改用它:

?- write_term(foo, [portray(true)]).
'foo'.

要在 atom 中添加转义字符的额外要求,您需要将自己的 DCG 实现为转义字符的 ISO 标准,或者滥用内置的 DCG。为此,您可以写出一个原子,看看是否需要添加单引号,或者它们是否已经存在。 X = (\). 的大小写在其自己的子句中最容易处理,然后您可以选择是否要打印 '\'(\).

portray(\) :-
    format("'\\'"), !.
portray(Term) :-
    atom(Term), \+ Term = (\),
    ( with_output_to(chars(['\''|_]),
        write_term(Term, [quoted(true), character_escapes(true), portrayed(false)]))
    -> format("~q", Term)
    ; format("'~s'", Term)
    ).