Use portray_clause/1 for listing clauses. This predicate must ensure that reading returns the same clause given the same operator declarations.
Use print/1 only for debug/3 and other interactive use of your program.
Be careful with 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 is such as beast for dealing with RDF.
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 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.
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: