When format, ansi_format, print_term and print_message don't seem right, try portray

For printing messages:

Most of the time what is printed is just a simple message and format/2,3 will work.
When a messages needs some color ansi_format/3 (example) will work.
When you need to print messages in other languages and for other output devices or need to hook into the printing sequence, print_message/2 (tutorial) comes to the rescue.

For printing structures:

When the term is a large structure, print_term/2 comes to the recuse.


When all of these don’t seem right, take a look at portray/1. There is a really nice example of this for displaying a Rubick’s Cube. (ref)


EDIT

Example code for parsing ABNF from text to structure using DCG and converting structure back into text using portray/1 - EricGT/ABNF. Code has fixed_point_check/1.

And then we learn something more.
See: How to disable specific multifile predicates? i.e. portray(cr(A))


For completeness sake.

pprint.pl – Pretty Print Prolog terms

2 Likes

If you use portray/1, I suggest wrapping it:

user:portray(Term) :-
    % fail,  % Uncomment this line to turn off my_portray/1
    % In the following, format/2 is used because
    % print_message(warning, E) gives an infinite recursion.
    E = error(_, _),  % avoid trapping abort, timeout, etc.
    catch(my_portray(Term),
          E,
          format('EXCEPTION:portray(~q)', [Term])).

my_portray(...) :- ...
1 Like

Another trick for portray/1: don’t use unification in the head (because uninstantiated variables can become instantiated). Instead do something like this:

my_portray(Term) :-
    my_portray_unify(foo(X,Y,Z), Term),
    format('foo(~p,~w,~q)', [X,Y,Z]).

my_portray_unify(Generic, Term) :-
    subsumes_term(Generic, Term),
    Generic = Term.

Alternatively, use “not-not” (\+ \+) to undo any unification.

2 Likes