首页 > 解决方案 > 如何让 SWI-Prolog 在交互模式下始终打印带引号的字符串

问题描述

使用 SWI-prolog 时,它将打印不需要引号的输出(不包含特殊字符的输出),不带引号。举个例子:

?- p('this_is_a_string').
true.

?- p(X).
X = this_is_a_string.

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

标签: prologswi-prolog

解决方案


要更改 SWI-Prolog 顶级输出的默认行为,您需要设置一个 flag。如果您查询适当的标志,您应该会发现这是您的默认输出:

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

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

portray/1是您可以断言的动态谓词。它在打印时使用基本术语调用,如果成功,则假定该术语已被打印。

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

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

要在原子中添加转义字符的额外要求,您需要根据 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)
    ).

推荐阅读