# Best practices for printing

**URL:** <https://swi-prolog.discourse.group/t/best-practices-for-printing/4231>\
**Category:** Nice to know\
**Tags:** best\_practices, printing\
**Created:** [August 1, 2021, 9:45am UTC](https://swi-prolog.discourse.group/t/best-practices-for-printing/4231 "2021-08-01T09:45:30Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Wiki](https://avatars.discourse-cdn.com/v4/letter/w/e8c25b/32.png) [@Wiki](https://swi-prolog.discourse.group/u/Wiki)\
**Post date:** [August 1, 2021, 9:45am UTC](https://swi-prolog.discourse.group/t/best-practices-for-printing/4231/1 "2021-08-01T09:45:30Z")

</div>

This is from a [reply](https://swi-prolog.discourse.group/t/odd-behaviour-with-expects-dialect-sicstus/4217/10) by Jan W.

Best practice seems to be

- Use [format/3](https://www.swi-prolog.org/pldoc/doc_for?object=format/3) to emit non-term output.
- When writing a library, use the [print\_message/2](https://www.swi-prolog.org/pldoc/doc_for?object=print_message/2) indirection for talking to the user.
- Use [writeq/1](https://www.swi-prolog.org/pldoc/doc_for?object=writeq/1) or [write\_canonical/1](https://www.swi-prolog.org/pldoc/doc_for?object=write_canonical/1) to write terms that need to be read by Prolog.
- Use [portray\_clause/1](https://www.swi-prolog.org/pldoc/doc_for?object=portray_clause/1) for listing clauses. This predicate must ensure that reading returns the same clause given the same operator declarations.
- Use [print/1](https://www.swi-prolog.org/pldoc/doc_for?object=print/1) only for [debug/3](https://www.swi-prolog.org/pldoc/doc_for?object=debug/3) and other interactive use of your program.
- Be careful with [portray/1](https://www.swi-prolog.org/pldoc/doc_for?object=portray/1). Only use it for very specific terms for libraries or better, include a dedicated portray library for a specific library. [rdf\_portray.pl](https://github.com/SWI-Prolog/packages-semweb/blob/master/rdf_portray.pl) is such as beast for dealing with RDF.
- [write/1](https://www.swi-prolog.org/pldoc/doc_for?object=write/1) should never have been added to Prolog.

---

<div class="post-metadata">

**Author:** ![dgelessus](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/dgelessus/32/3106_2.png) [@dgelessus](https://swi-prolog.discourse.group/u/dgelessus)\
**Post date:** [August 1, 2021, 12:28pm UTC](https://swi-prolog.discourse.group/t/best-practices-for-printing/4231/3 "2021-08-01T12:28:30Z")

</div>

Also worth mentioning IMO:

- write\_term/2 if you want to print a term and need finer control over how quoting, operators, variables, etc. are handled
- [print\_term/2](https://www.swi-prolog.org/pldoc/doc_for?object=prolog_pretty_print%3Aprint_term/2) from library(pprint) pretty-prints terms with more human-readable formatting, and has some extra options to control this
- write\_canonical/1 on SWI prints lists using list syntax and not as compound terms, as this would expose SWI’s `'[|]'` list term functor. If this is a problem and you really need it printed in plain compound term syntax, use write\_term/2 with the option `dotlists(true)` or `no_lists(true)` (depending on whether you want lists to be printed using the traditional `'.'` functor or SWI’s `'[|]'` functor). Note that these options are SWI-specific - on other Prolog systems, the `ignore_ops` option controls whether list syntax is used.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [November 20, 2021, 12:02am UTC](https://swi-prolog.discourse.group/t/best-practices-for-printing/4231/4 "2021-11-20T00:02:09Z")

</div>

Another way of getting finer control is to “print” to a string and then modify it, by using with\_output\_to/2 and the `current_output` stream alias. For example:

```prolog
print_term_cleaned(Term, Options) :-
    with_output_to(string(TermStr0),
        print_term(Term, [tab_width(0),output(current_output)|Options])),
    re_replace(" +\n"/g, "\n", TermStr0, TermStr1), % remove trailing whitespace
    re_replace("\t"/g, " ", TermStr1, TermStr). % replace tabs by blanks
    write(TermStr).

```

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [March 24, 2022, 9:00am UTC](https://swi-prolog.discourse.group/t/best-practices-for-printing/4231/5 "2022-03-24T09:00:47Z")

</div>

For SWISH consider

- [rendering](https://swish.swi-prolog.org/example/rendering.swinb)
- [projections](https://swish.swi-prolog.org/example/projections.swinb)

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [January 12, 2023, 9:34am UTC](https://swi-prolog.discourse.group/t/best-practices-for-printing/4231/6 "2023-01-12T09:34:32Z")

</div>

From this [reply](https://swi-prolog.discourse.group/t/creating-pairs-of-variables-from-a-clause/6085/16) by Jan W.

… one should be aware that calling write/1 twice on the same variable may not print the same value. This is because the print output are stack offsets and GC changes these. There is not a good way around that. For this type of exploration you may consider

?- set\_prolog\_flag(gc, false).  
to disable garbage collection. Be careful, you easily run out of memory.

As is, variables appearing in a term that is printed as a whole are consistent, unless portray hooks are used. Printing a term reliably is pretty hard. The toplevel uses copy\_term/3 to move the constraints out, if the term is cyclic it factorizes the cycles. Next it uses numbervars/4 with the singletons(true) argument and finally prints using portray and numbervars options.
