Use `print` and `~p` instead of `write_term` and `~w`

Basically, I want the terms as answers and the terms for printing to be the same.

The default values of the flag answer_write_options is:

?- current_prolog_flag(answer_write_options, Value).
Value = [quoted(true), portray(true), max_depth(10), spacing(next_argument)].

The default value of the flag print_write_options is:

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

Notice that these two default values are not exactly the same. So yes, by default the terms as answers and the terms for printing are not the same.

For example:

?- Term = '$VAR'(10), print(Term).
'$VAR'(10)
Term = K.
?- Term = foo(1,2,3), print(foo(1,2,3)).
foo(1,2,3)
Term = foo(1, 2, 3).
?- Term = [1,2,3,4,5,6,7,8,9,10,11,12,13], print(Term).
[1,2,3,4,5,6,7,8,9,10,11,12,13]
Term = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].

But we can make them be the same! Just setting them in the init.pl:

For example,

:- set_prolog_flag(print_write_options, [portray(true), quoted(true)]).
:- set_prolog_flag(answer_write_options, [portray(true), quoted(true)]).

Then everything is OK:

?- Term = '$VAR'(10), print(Term).
K
Term = K.

?- Term = foo(1,2,3), print(foo(1,2,3)).
foo(1,2,3)
Term = foo(1,2,3).

?- Term = [1,2,3,4,5,6,7,8,9,10,11,12,13], print(Term).
[1,2,3,4,5,6,7,8,9,10,11,12,13]
Term = [1,2,3,4,5,6,7,8,9,10,11,12,13].

However, there is no flag for write_term/2, i.e. you cannot set default Options for write_term/2 (at least I didn’t find…). So when you want to write a term, you have to do, for example,

?- Term = '$A'(0), write_term(Term, [quoted(true)]).
'$A'(0)
Term = '$A'(0).

or

?- Term = '$A'(0), format("~W~n", [Term, [quoted(true)]]).
'$A'(0)
Term = '$A'(0).

This is obviously not convenient. The better way is using print/1 and format/3 with ~p, because they can have default values:

?- Term = '$A'(0), print(Term).
'$A'(0)
Term = '$A'(0).

or

?- Term = '$A'(0), format("~p~n", Term).
'$A'(0)
Term = '$A'(0).

BTW, I saw many people using writeln/1, write_term/2, ~w in format/3, etc for printing, which is not ideal IMO, because it would make the answer terms inconsistent with the printed terms (notably for quoted atoms).

This is what I learnt today.

1 Like

Whether you want space on the next argument or not is personal taste. Omitting the depth limit for answers is not something I’d not recommend. You typically do not want a list with 1M elements printed. print/1 is mainly for debugging purposes. Using a depth limit there might actually be a good idea as well. write/1, as I have argued before, is a weird predicate. t doesn’t quote and thus the result cannot be read by Prolog. format/3 makes more sense when emitting something for human consumption. write_term/2 is useful as it provides a lot of control on the output, most of which proved to be useful in particular contexts.

1 Like