PmWiki
pmwiki.org
edit SideBar
|
Non-standard write-options for write_term/3
Author: Joachim Schimpf, 2013, 2024
The ISO-Prolog Standard defines the following required write-options in section 7.10.4.
- quoted(Bool)
- Iff Bool (7.1.4.2) is true each atom and functor is quoted if this would be necessary for the term to be input by read_term/3. In addition, floats must be printed with sufficient precision to allow them to be read back exactly.
- ignore_ops(Bool)
- Iff Bool (7.1.4.2) is true each compound term is output in functional notation (6.3.3). Neither operator (6.3.4.3) notation nor list notation (6.3.5) is used when this write-option is in force. In Corrigendum 3 this was extended to apply to the printing of {}/1 terms too.
- numbervars(Bool)
- Iff Bool (7.1.4.2) is true a term of the form '$VAR'(N), where N is an integer, is output as a variable name consisting of a capital letter possibly followed by an integer. The capital letter is the (i+1)th letter of the alphabet (see the syntax rule for capital letter char, 6.5.2), and the integer is j, where i = N mod 26, j = N // 26. The integer j is omitted if it is zero.
The following option was added via corrigendum 3:
- variable_names(List)
- Assign names to variables in Term. List is a list of terms Name = Var, where Name is an atom that represents a valid Prolog variable name. Terms where Var is bound or is a variable that does not appear in Term are ignored.
A processor may support one or more additional write-options as an implementation specific feature. We suggest that systems doing so aim to be compatible with the following suggestions.
Options meaningful for every ISO system:
- nl(Bool) (ECLiPSe/SWI)
- If true, print a newline sequence (as with nl/1) after the term. If this is used together with the fullstop(true) option, this newline serves as the blank space after the fullstop. Default false.
- fullstop(Bool) (ECLiPSe/SWI)
- If true, terminate the term with a fullstop (a dot followed by blank space), so it can be read back. The blank space after the dot is a newline if the nl(true) option is present, otherwise a space character. If necessary, an extra space will be inserted before the fullstop, in order to separate it from the end of the term.
- priority(Prec) (Sicstus,SWI,GP,Ciao,ECLiPSe,XSB) or precedence(Prec) (ECLiPSe)
- Prec is an integer between 0 and 1200 (default 1200), representing context operator precedence. Can be used to force correct parenthesizing when partial terms are written as arguments of operators. The written term will be enclosed in parentheses if its precedence is higher than Prec.
- max_depth(N) (Sicstus,SWI,ECLiPSe,GP,Ciao,XSB) or maxdepth(N) (IF)
- If MaxDepth is a positive integer, print the term only up to a maximum nesting depth of MaxDepth, and represent more deeply nested subterms as ... . If 0, impose no depth limit. IF-Prolog also has maxdepth(N,TermAbbrev,ListAbbrev) for specifying the atoms that are used to abbreviate the omitted subterms. In SWI, this is interpreted specially for lists.
- flush(Bool) (ECLiPSe)
- If true, flush the stream (as with flush/1) after the term hash been printed. Default false.
Special syntax for certain functors:
- dotlists(Bool) (ECLiPSe,SWI)
- If false (default), write lists in the common square bracket notation, e.g. [1, 2]. If true, write lists in the dot functor notation, e.g. .(1, .(2, [])). This is subsumed by the ISO ignore_ops option. SWI also has no_lists(Bool).
- brace_terms(Bool) (SWI)
- If true (default), write {}(X) as {X}. This is subsumed by the ISO ignore_ops option.
- operators(true) (ECLiPSe)
- If true (default), write operators in pre/in/postfix notation. Unlike ISO ignore_ops, this does not affect printing of lists and brace-terms. Note that SWI's (non-ISO) ignore_ops is the negation of this.
In the case where options conflict, the more specific one should take precedence, e.g. dotlists over ignore_ops.
Layout options:
- spacing(Atom) (SWI) or compact(Bool) (ECLiPSe) or space_args(Bool) (GP)
- Specifies whether and where to print extra spaces for readability. TBD: agree on default and possible values, e.g. minimal, standard, next_argument, around_operators, etc. .
- indented(Bool) (SICStus)
- The term is printed with the same indentation as is used by portray_clause/1 and listing/[0,1].
- character_escapes(Bool) (SWI)
- If true and quoted(true) is active, special characters in quoted atoms and strings are emitted as ISO escape sequences.
- newlines(Bool) (ECLiPSe)
- If true and quoted(true) is active, print newlines as newlines (and tabs as tabs) even inside quotes (rather than as escape sequence).
Options for number formatting:
- float_format(Atom) (Sicstus)
- How to print floats. This is sensible, but unfortunately defined in terms of non-standard format/2,3. IF-Prolog may have a better format spec for its float_format/2 builtin.
- float_precision(Prec) (XSB)
- Prec must be an integer between 1 and 17, and this number determines the precision with which a floating point number is displayed, (excluding trailing zeros). The default value is 15. Should there be an option for "as many digits as necessary for reading back" (which is currently a side effect of quoted(true))?
- float_width(Width) (XSB)
- Width must be an integer between 1 and 17, and this number determines the minimum width precision with which a floating point number is displayed. For instance, a width of 2 ensures that a floating point number is always displayed with a decimal value. The default value is 2. Could this be subsumed by a general width-option?
- float_specifier(Spec) (XSB)
- Floats in XSB are printed using underlying C routines. In C a floating point specifier of f or F means that a floating point number is always printed with a certain precision, while a specifier of g or G truncates trailing zeros. The allowed values are g,G,f and F. The default value is g.
- radix(Radix) (XSB)
- Ensures that integers are printed with radix Radix. Radix can be decimal, hex or octal. The default is decimal. TBD: why not use/allow integer radix, and flag to print the corresponding radix prefix (Radix'Number, 0xNumber, etc)?
Options meaningful only with other extensions:
- portrayed(Bool) (Sicstus,ECLiPSe,IF,GP,Ciao,SWI) or portray(Bool) (SWI)
- If true, call the user-defined predicate portray/1,2 in the way print/1,2 does. Note that print/portray/1 is traditional. ISO doesn't define print/portray at all. ECLiPSe prefers print/portray/2 with stream argument.
- attributes(Atom) (ECLiPSe,SWI)
- Determines how variable attributes are printed. Options are: do not print attributes (none or ignore); print {...} (dots); print the attributes as subterms surrounded by curly braces (full or write); pretty-print the arrtributes (pretty or portray). Default is none. TBD: agree on the names.
- cycles(Bool) (Sicstus,SWI)
- If true (default), cyclic terms are written as @(Template, Substitutions), where Substitutions is a list Var = Value. TBD: since this syntax conflicts with other uses of @/2, it would be preferable to have cycles(Atom) to be able to specify different alternatives for representing cycles.
Miscellaneous:
- as(Kind) (ECLiPSe)
- Where Kind is 'clause', 'goal' or 'term': assume that the printed term is of the given Kind, and apply the corresponding transformations before printing.
- legacy_numbervars(Bool) (SICStus)
- Like numbervars, but with the more permissive pre-ISO convention for printing variable names: if the argument of '$VAR'(N) is an atom or code list, these characters are written instead of the term.
- namevars(Bool) (GP)
- A term of the form ’$VARNAME’(Name), where Name is an atom respecting the syntax of variable names, is output as a variable name (see below). Like numbervars, but with the more permissive pre-ISO convention for printing variable names: if the argument of '$VAR'(N) is an atom or code list, these characters are written instead of the term.
- variables(Method) (ECLiPSe)
- How to print variables:
default: print variables using their source name, if available. Otherwise print a system-generated name, which consists of an underscore and a number, e.g. _123. Note that this format cannot be reliably read back, because different variables may have the same source name. raw: print all variables using a system-generated name, which consists of an underscore and a number, e.g. _123. This format is suitable when the term needs to be read back later. It makes sure that multiple occurrences of the same variable have the same name, and different variables have different names. full: print variables using their source name, if available, followed by a unique number, e.g. Alpha_132. Variables without source name are printed in the raw format. Since variables with identical source names are named apart, this format is suitable when the term needs to be read back later. anonymous: print every variable as a simple underscore. Any information about multiple occurrences of a variable is lost with this format. It is mainly useful to produce output that can be compared easily with the output of a different session.
Guidelines for adding options
The functionality of write_term overlaps with the functionality of format/printf. Trying to support all format/printf functionality in write_term may lead
to a confusing proliferation of options, and multiple ways of doing the same thing. This should be kept in check by considering that
- format/printf is about embedding one (or multiple) small (often atomic) Prolog terms into a printed text string. The focus is on how each embedded term is laid out individually.
- write_term is about printing a single (possibly complex) Prolog term. The focus is on globally controlling the layout of a unknown number of subterms of varying types.
Some options may seem redundant, e.g. write_term(T,[nl(true)]) can be written as write_term(T,[]),nl . However, they are useful in a multi-threaded context, where a single write_term goal might be guaranteed to be an atomic operation, while the two-goal sequence may be interrupted by another thread printing to the same stream.
Issues to be resolved
- Treatment of unknown/unsupported options: error, silent ignore, warning, or? ISO requires error, SWI ignores silently
- SWI allows
option_name as abbreviation for option_name(true) , which seems convenient and sensible
- Is there a need for an option to write character lists as text?
|