Comments on format tests

Thanks for the tests, @jschimpf. I added support for expressions for *. That reduces the failures from 10 to 5. Also restricted ~a to atoms and strings, leaving 4 discrepancies. Now it gets interesting.

  • format('a~3N~3Nb',[]). We agreed to ignore the argument. It seems my current code does use it, meaning the the same as ~3n if not at 0 and ~2n if at 0. I’m afraid I do not have access to the original Quintus docs, so I do not know whether it came from there. I am quite sure I tried to replicate the original as close as possible.
  • The other three have to do with multiple ~t if the space cannot be evenly distributed, i.e., the required padding is not a multiple of the number of ~t sequences. Apparently you use a different algorithm to spread the extra spaces over the ~t. SWI-Prolog distributes the additional space from the center, i.e., adding a space to the middle ~t, then one to the right of the middle, than one to the left, than 2 to the right, 2 to the left, etc. until all required spaces are allocated. Should the algorithm be specified

In the string section, we have

  • format("~a",[hello]) should_output "hello". I think that is wrong. A string represented as a list is ambiguous (except for SWI-Prolog :slight_smile: ), so I think the error SWI-Prolog raises is correct.

The Quintus docs are at Quintus format/2,3. They specify an argument only for ~n, not ~N. Same for SICStus. GNU-Prolog has a different interpretation from yours. This was the reason to ignore the argument in the PIP:

System ~N ~1N ~3N ~0N
Quintus (manual) 1 newline, 0 when at BoL ? ? ?
SICStus (manual) 1 newline, 0 when at BoL ? ? ?
Ciao 1.25.0 1 newline, 0 when at BoL 1 newline, 0 when at BoL error error
GNU Prolog 1.4.4 1 newline, 0 when at BoL 1 newline, 0 when at BoL 3 newlines, 0 when at BoL 1 newline, 0 when at BoL
SWI 9.3.34 1 newline, 0 when at BoL 1 newline, 0 when at BoL 3 newlines, 2 when at BoL 0 newlines
XSB 5.0.0 0 newlines 0 newlines error error
PIP draft (argument ignored) 1 newline, 0 when at BoL 1 newline, 0 when at BoL 1 newline, 0 when at BoL 1 newline, 0 when at BoL

The Quintus manual example only shows the case of two ~t, where the single extra space goes to the right hand side. I generalised this so that every ~t gets the same or 1 more spaces than all the preceding ones, i.e. they are evenly spread with a bias to the right.
We should probably follow the precedent of Quintus/SICStus – can someone try their behaviour?

SICStus satisfies your tests (on distributing ~t). I’ve updated SWI-Prolog to insert the extra spaces from the right. Also now ignore the argument to ~N, so it passes all tests. Added the test file to SWI-Prolog’s test suite (I already had the driver from our string work).

Using 9.3.34-30-g60abbc3bf:

$ logtalk_tester -p swi
% Batch testing started @ 2025-11-13 14:33:27
% Logtalk version: 3.96.0-b01
% SWI-Prolog version: 9.3.34
% OS version: Darwin, x86_64, 23.6.0
%
% logtalk/tests/prolog/predicates/format_2
% 96 tests: 0 skipped, 87 passed, 9 failed (0 flaky)
% completed tests from object tests_atom in 2 seconds
% 96 tests: 0 skipped, 87 passed, 9 failed (0 flaky)
% completed tests from object tests_codes in 2 seconds
% 96 tests: 0 skipped, 87 passed, 9 failed (0 flaky)
% completed tests from object tests_chars in 2 seconds
% clause coverage n/a
%
% Compilation errors/warnings and failed unit tests
% (compilation errors/warnings might be expected depending on the test)
! lgt_format_2_string_pad_with_spaces: failure (in 0.000182000/0.001000000 cpu/wall seconds)
! test assertion failed: ‘ABC ‘==‘ABC’
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 141-144
!
!
! lgt_format_2_partial_list_second_argument_1: failure (in 0.000087000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(instantiation_error,A)
! but got error(type_error(,[42|B]),context(system:format/2,’“x” must hold one character’))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 518-520
!
!
! lgt_format_2_partial_list_second_argument_2: failure (in 0.000086000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(instantiation_error,A)
! but got error(type_error(,[42|B]),context(system:format/2,‘“x” must hold one character’))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 522-524
!
!
! lgt_format_2_second_argument_wrong_type: failure (in 0.000079000/0.001000000 cpu/wall seconds)
! test goal succeeded but should have thrown an error:
! expected error(type_error(list,42),A)
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 530-532
!
!
! lgt_format_2_invalid_argument_1: failure (in 0.000094000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(type_error(A,B),C)
! but got error(format_argument_type(a,42),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 534-536
!
!
! lgt_format_2_not_enough_arguments_1: failure (in 0.000087000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘not enough arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 542-544
!
!
! lgt_format_2_not_enough_arguments_2: failure (in 0.000088000/0.001000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘not enough arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 546-548
!
!
! lgt_format_2_too_many_arguments_1: failure (in 0.000094000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘too many arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 550-552
!
!
! lgt_format_2_too_many_arguments_2: failure (in 0.000096000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘too many arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_atom.lgt between lines 554-556
!
!
! lgt_format_2_string_pad_with_spaces: failure (in 0.000187000/0.000000000 cpu/wall seconds)
! test assertion failed: ‘ABC ‘==‘ABC’
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 141-144
!
!
! lgt_format_2_partial_list_second_argument_1: failure (in 0.000083000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(instantiation_error,A)
! but got error(type_error(,[42|B]),context(system:format/2,’“x” must hold one character’))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 518-520
!
!
! lgt_format_2_partial_list_second_argument_2: failure (in 0.000088000/0.001000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(instantiation_error,A)
! but got error(type_error(,[42|B]),context(system:format/2,‘“x” must hold one character’))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 522-524
!
!
! lgt_format_2_second_argument_wrong_type: failure (in 0.000080000/0.000000000 cpu/wall seconds)
! test goal succeeded but should have thrown an error:
! expected error(type_error(list,42),A)
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 530-532
!
!
! lgt_format_2_invalid_argument_1: failure (in 0.000092000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(type_error(A,B),C)
! but got error(format_argument_type(a,42),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 534-536
!
!
! lgt_format_2_not_enough_arguments_1: failure (in 0.000086000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘not enough arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 542-544
!
!
! lgt_format_2_not_enough_arguments_2: failure (in 0.000085000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘not enough arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 546-548
!
!
! lgt_format_2_too_many_arguments_1: failure (in 0.000093000/0.001000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘too many arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 550-552
!
!
! lgt_format_2_too_many_arguments_2: failure (in 0.000094000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘too many arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 554-556
!
!
! lgt_format_2_string_pad_with_spaces: failure (in 0.000177000/0.000000000 cpu/wall seconds)
! test assertion failed: ‘ABC ‘==‘ABC’
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 141-144
!
!
! lgt_format_2_partial_list_second_argument_1: failure (in 0.000083000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(instantiation_error,A)
! but got error(type_error(,[42|B]),context(system:format/2,’“x” must hold one character’))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 518-520
!
!
! lgt_format_2_partial_list_second_argument_2: failure (in 0.000086000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(instantiation_error,A)
! but got error(type_error(,[42|B]),context(system:format/2,‘“x” must hold one character’))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 522-524
!
!
! lgt_format_2_second_argument_wrong_type: failure (in 0.000081000/0.000000000 cpu/wall seconds)
! test goal succeeded but should have thrown an error:
! expected error(type_error(list,42),A)
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 530-532
!
!
! lgt_format_2_invalid_argument_1: failure (in 0.000092000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(type_error(A,B),C)
! but got error(format_argument_type(a,42),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 534-536
!
!
! lgt_format_2_not_enough_arguments_1: failure (in 0.000084000/0.001000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘not enough arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 542-544
!
!
! lgt_format_2_not_enough_arguments_2: failure (in 0.000084000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘not enough arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 546-548
!
!
! lgt_format_2_too_many_arguments_1: failure (in 0.000090000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘too many arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 550-552
!
!
! lgt_format_2_too_many_arguments_2: failure (in 0.000093000/0.000000000 cpu/wall seconds)
! test goal throws the wrong error:
! expected error(domain_error(A,B),C)
! but got error(format(‘too many arguments’),context(system:format/2,D))
! while compiling file
! in file logtalk/tests/prolog/predicates/format_2/tests_chars.lgt between lines 554-556
!
!
%
% Failed tests
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_string_pad_with_spaces @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_partial_list_second_argument_1 @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_partial_list_second_argument_2 @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_second_argument_wrong_type @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_invalid_argument_1 @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_not_enough_arguments_1 @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_not_enough_arguments_2 @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_too_many_arguments_1 @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_atom.lgt - lgt_format_2_too_many_arguments_2 @ tests_atom
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_string_pad_with_spaces @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_partial_list_second_argument_1 @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_partial_list_second_argument_2 @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_second_argument_wrong_type @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_invalid_argument_1 @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_not_enough_arguments_1 @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_not_enough_arguments_2 @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_too_many_arguments_1 @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_codes.lgt - lgt_format_2_too_many_arguments_2 @ tests_codes
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_string_pad_with_spaces @ tests_chars
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_partial_list_second_argument_1 @ tests_chars
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_partial_list_second_argument_2 @ tests_chars
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_second_argument_wrong_type @ tests_chars
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_invalid_argument_1 @ tests_chars
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_not_enough_arguments_1 @ tests_chars
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_not_enough_arguments_2 @ tests_chars
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_too_many_arguments_1 @ tests_chars
logtalk/tests/prolog/predicates/format_2/tests_chars.lgt - lgt_format_2_too_many_arguments_2 @ tests_chars
%
% 1 test sets: 1 completed, 0 skipped, 0 broken, 0 timedout, 0 crashed
% 288 tests: 0 skipped, 261 passed, 27 failed (0 flaky)
%
% Batch testing ended @ 2025-11-13 14:33:29

The exact exceptions in case of error is the least standardized aspect. But the first three errors (repeated for atom, chars, and codes) should be addressed. The first test also fails for ECLiPSE 7.2.#5. But it passes for other systems, including SICStus Prolog.

Thanks for stepping in.

To make progress, the PIP working group doesn’t care too much about precise errors unless it is likely that the user might wish to catch them and act differently than just reporting. Some typically examples are arithmetic evaluation errors, file open errors, etc.

To be precise, I think this is about an argument to ~a and ~s, which should be interpreted as truncating the atom/string if too long and right-padding if too short, right?

test(lgt_format_2_string_pad_with_spaces, true(Assertion)) :-
	^^set_text_output(''),
	{format("~6s", [[65,66,67]])},
	^^text_output_assertion('ABC   ', Assertion).

In yesterdays PIP meeting it was decided to include padding with ~s. I just pushed a commit to SWI-Prolog implementing this. It was also felt that this is not in the spirit of these predicates as padding is implemented using ~t in a much more flexible (but more verbose) way. In the end, existing practice was the main motivation to support padding in ~6s.

It may seem a small step, but I’m really glad to see many Prolog systems implementing pretty compatible versions of the format family predicates!

Great! Other systems besides SICStus Prolog (e.g. Trealla Prolog and XVM) already implemented the padding.

Btw, I understand the issues of attempting to standardize all exceptions at this point, specially in case of the `format/2-3` predicates are same of them are consistency errors and ISO defined error terms really don’t fit (hence my suggestion elsewhere for a `consistency_error/3` exception). Still, the instantiation errors I pointed above should not be challenging?

I agree completely! :slight_smile:

Answering some of the Joachim questions above:

  1. A format/2-3 goal where the first argument is a double-quoted term should work independently of the value of the double_quotes flag. This is already true for most systems implementing these predicates. That flag is a nuisance. Small wins.
  2. Both SWI-Prolog ~W and XVM solution to specify term printing depth (for ~w, ~q, and ~k) are proprietary. Consensus is needed here.
  3. Specifying term printing depth is orthogonal to ~w, ~q, and ~k. I don’t understand why Joachim claims it to be only relevant to ~w.
  4. For testing with GNU Prolog, use the latest git version (pre-release of 1.6.0) as it includes fixes/changes for the format/2-3 predicates.

Just a followup on the instantiation errors, in the particular case of latest SWI-Prolog git:

!     lgt_format_2_partial_list_second_argument_1: failure (in 0.000084000/0.000000000 cpu/wall seconds)
!       test goal throws the wrong error:
!         expected error(instantiation_error,A)
!         but got  error(type_error(
,[42|B]),context(system:format/2,‘“x” must hold one character’))
!       while compiling file
!       in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 518-520
!
!
!     lgt_format_2_partial_list_second_argument_2: failure (in 0.000088000/0.000000000 cpu/wall seconds)
!       test goal throws the wrong error:
!         expected error(instantiation_error,A)
!         but got  error(type_error(
,[42|B]),context(system:format/2,‘“x” must hold one character’))
!       while compiling file
!       in file logtalk/tests/prolog/predicates/format_2/tests_codes.lgt between lines 522-524


Not only the arguments of the type_error/2 are confusing, the exceptions leak implementation details (‘“x” must hold one character)! For reference, the tests are:

test(lgt_format_2_partial_list_second_argument_1, error(instantiation_error)) :-
	^^set_text_output(''),
	{format("~d", [42| _])}.

test(lgt_format_2_partial_list_second_argument_2, error(instantiation_error)) :-
	^^set_text_output(''),
	{format("~d ~d", [42| _])}.

I’m in the position that the exact exception is irrelevant except for predicates where users may wish to act on the exception. format/2 is not one of these. The only purpose of its exceptions is to help the programmer to debug them. I do agree that the error for evaluating an expression holding e.g., [42|_] could be better. I pushed an update to that. The

is a comment to the exception. It works reasonable for an invalid arithmetic expression as "ab". On the other hand, it is rather unlikely anyone would write [42|_] or even the correct [42] in an expression. I surely do not know whether an instantiation error is the best. The downside is that it carries very little (no :frowning: ) context. And what about [42,43|_]? There is no need for the implementation to examine the whole list and SWI-Prolog doesn’t do so. It sees a list cell, checks the 2nd arg to be [] and complains otherwise.

IMO, too many Prolog standardization efforts failed or were delayed for too long because of trying to standardize exceptions. The overall scheme of the ISO exceptions is reasonable. Some fit the scheme rather poorly. Two correct arguments that cannot go together is indeed one of them. I also added a 3 argument existence_error version, adding an argument that tells where the thing does not exist (for example a key in a dict). Also OS errors are problematic. For example when opening a file we have permission_error and existence_error (in addition to various errors due to invalid arguments). Actually trying to open a file has a bunch more errors though. You may run into resource errors (file handles), I/O errors, too deep chains of symlinks and a lot more. I’d be interested in fixing that as these errors are important and you may want to act on the specific problem.

There’s a continuum between not caring about the exact exceptions and being absolutely strict about them. But having a call using ~d and the error saying the “x” must hold a character is misleading and certainly doesn’t help debugging. Ignoring standardization efforts, it also makes the system inconsistent as instantiation errors are used in other cases. Of course, these issues exist elsewhere (e.g. ECLiPSe non-descriptive “abort”). But this specific case seems to me to be low hanging fruit and easy to improve on.

While I do not like continuing this discussion, I think there is a misconception. As most traditional format/2 implementations, if the argument list is not a list, it is processed as a list holding a single argument. This results in

format('~d', [42|_])

to be processed as

format('~d', [[42|_]])

Now, as we accept arithmetic expressions for ~d, the error comes from evaluating the traditional one-element-list as a character code. Hence the rather weird error.

I agree that is wrong. We should only do the single argument handling if the argument is not a list cell. Note that non-lists are already deprecated. For a good reason. Just, I’m afraid there will be a lot of complains if this old feature is actually removed :frowning:

We should probably not talk about “proprietary” when referring to ideas or free implementations (XVM might be different, I don’t know).

We included ~W (upper-case!) in PIP-0110 despite not yet being widely implemented, because

  • like ~w, ~q, ~k it can be defined by simply referring to an existing ISO-standard built-in
  • it is trivial to implement by mapping to the write_term/3 built-in
  • it covers (at least potentially, see PIP-0105) not only print depth, but many other write-options as well

The options ~w, -p, ~q, ~k are historically defined as passing the argument to write/2, print/2, writeq/2 and write_canonical/2, respectively. If you add further parameters, this must be changed. ISO does not say anything about depth limits, but I believe there is consensus that writeq and write_canonical must produce a format that can be read back, which makes ~q and ~k incompatible with a depth limit.

Moreover, once you start adding parameters to ~w, it becomes natural to expect control over all print options – ECLiPSe’s printf/3 went down that route by recognising depth plus 19(!) modifier characters in its %w format, so you can write things like printf("%10QOIMTw", [Term]). Delegating to write_term/3 is probably a nicer solution.

Finally, the PIP-0110 Draft stipulates that a numeric parameter (such as in ~3w) shall be ignored (instead of raising an error) when it is not recognised by a format. This makes it possible to implement your scheme as an extension, without violating the PIP.

Sorry for the late reply. In the just release Logtalk 3.96.0 version, I updated the `format` library linter to account for the `~W` option. At Permion, we’re updating XVM implementation of the `format/2-3` predicates for the proposal.

Regarding write depth and option such as `~q` or `~k`, a practical example is in the context of a debugger where the user may want other print a term quoted and ignoring operators while still controlling the write depth. The `max_depth/1` have become a de facto standard `write_term/2-3` option. For example, using latest GNU Prolog git version:

| ?- length(L, 10000000), write_term(L, [quoted(true), ignore_ops(true), max_depth(7)]).
‘.’(_307,‘.’(_309,‘.’(_311,‘.’(_313,‘.’(_315,‘.’(_317,‘.’(_319,…)))))))

I agree that the `~W` control sequence is the more versatile option here.

P.S. My use of the word “proprietary” is as “non-standard”, not about open source / commercial Prolog implementations (XVM is commercial, btw).

Logtalk tests for the format/2-3 predicates updated for the PIP-0110 proposal. XVM now passes all tests. Trealla Prolog is being updated for the proposal (only failing some of the table related tests as of v2.85.19). Failures when testing with ECLiPSe, SWI-Prolog, and SICStus Prolog are mostly about the exact exceptions or legacy backward compatibility support (and can thus be ignored). Are there any other Prolog systems currently being updated for the proposal that I missed?