Too many arguments to format/2

This surprised me a bit. I didn’t find it documented but historically I have been quite bad at reading the docs.

?- format("~w~n", [foo,bar]).
foo
true.

The opposite (not enough arguments) throws an error.

1 Like

GNU Prolog 1.4.5 and YAP 6.5.0 git behaves as SWI-Prolog for that query. But ECLiPSe 7.0#49 and SICStus Prolog 4.5.0 throw an error reporting the surplus bar argument. I considered in the past implementing a lint check for this case but it’s relatively heavy to parse and check the arguments at compile (also, the arguments may only be bound at runtime). It would be preferable that the predicate implementation itself generated an error (or at least a warning) in these cases.

1 Like

I would vote for format with wrong # of args should throw an error (either too few or too many). It’s a mistake I often make and I would rather see an error than incorrect output. (But what about this breaking existing code? I hear you ask, and I reply “It was wrong code, and it’s probably easily fixed”)

1 Like

I’m happy to add an error. What is the error term produced by SICStus and ECLiPSe? I don’t really see the obvious ISO style error term …

1 Like

ECLiPSe:

Version 7.0 #49 (x86_64_macosx), Wed Sep 18 19:49 2019
[user 36]: format("~w~n", [foo,bar]).
foo
bad argument list in format(output, "", [bar])
Abort

[user 37]: catch(format("~w~n", [foo,bar]), Error, true).
foo
bad argument list in format(output, "", [bar])
Error = abort
Yes (0.00s cpu)

SICStus Prolog:

$ sicstus
SICStus 4.5.0 (x86_64-darwin-17.7.0): Thu Jan 17 17:17:35 CET 2019
Licensed to Paulo Moura
% consulting /Users/pmoura/.sicstusrc...
% consulted /Users/pmoura/.sicstusrc in module user, 7 msec 45392 bytes
| ?- format("~w~n", [foo,bar]).
! Consistency error: [126,119,126,110] and user:[foo,bar] are inconsistent
! format_arguments
! goal:  format([126,119,126,110],user:[foo,bar])
| ?- catch(format("~w~n", [foo,bar]), Error, true).
Error = error(consistency_error([126,119,126,110],user:[foo,bar],format_arguments),consistency_error(format([126,119,126,110],user:[foo,bar]),[126,119,126,110],user:[foo,bar],format_arguments)) ? 
yes

Abort is a bit drastic. Interesting. Is this

consistency_error(Something, SomethingElse, WhyItIsInconsistent)?

My understanding is that, in ECLiPSe, most non-ISO errors throw an abort exception term. Joachim should be able to explain it better :stuck_out_tongue: You interpretation of the SICStus exception term is correct:
https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/ref_002dere_002derr_002dcns.html#ref_002dere_002derr_002dcns

Currently, I see:

$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.20-3-g369b0fa2a)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- format("~w~w", [1]).
1
ERROR: Format error: not enough arguments
ERROR: In:
ERROR:   [10] format("~w~w",[1])
ERROR:    [9] <user>
?- catch(format("~w~w", [1]), E, true).
1
E = error(format('not enough arguments'), context(system:format/2, _12930)).

?- format("~w", [1,2]).
1
true.

Do you mean that you’d like to change the error term for “not enough arguments” as well?

1 Like

Good question. Opinions? I guess we have two options:

  • format('too many arguments')
  • consistency_error(format(X, Y), X, Y, format_arguments) and use this also for all the other format errors.

Format/2,3 has quite a few currently fairly informative error messages. We map all of these to consistency errors and use the error/2 second field to retain the informative error messages? Does that make sense or is this a complete overkill? I’m tempted to consider this an overkill …

For the record, I have no strong opinion either way, as long as it is consistent. The lazy programmer in me tells me “whatever is the least work”.

too many arguments fits with the current too few arguments.

consistency_error feels like “I know more about the error but I won’t tell you.”
(And, yes, abort is too harsh.)

1 Like

With this patch we get

101 ?- format("~w~n", [foo,bar]).
foo
ERROR: Format error: too many arguments
ERROR: In:
ERROR:   [10] format("~w~n",[foo,bar])
ERROR:    [9] <user>
102 ?- 

Let us see whether that results in too many broken programs … Having a flag to suppress errors that will be in the system forever and needs documenting is no fun either.

2 Likes

10 posts were split to a new topic: Can I make Prolog’s “format/x” family behave leniently?

All in all, this did show some issues. I have added list_format_errors/0, part of check/0, so we now get:

t :-
	format("Hello ~w", ["World", "Universe"]),
	format(user_error, "Hello ~w", []),
	format(user_error, "Hello world").

t2 :-
	debug(foo, 'Hello ~w', []).

t3 :-
	format('See ~o', [hello]).
$ swipl s.pl
?- check.
% Checking undefined predicates ...
% Checking trivial failures ...
% Checking format/2,3 and debug/3 templates ...
Warning: /home/jan/src/swipl-devel/linux/s.pl:10:8: 
Warning:     format/2: Invalid template: format_character `o' does not exist
Warning: /home/jan/src/swipl-devel/linux/s.pl:7:8: 
Warning:     debug/3: Template requires 1 arguments, got 0
Warning: /home/jan/src/swipl-devel/linux/s.pl:2:8: 
Warning:     format/2: Template requires 1 arguments, got 2
Warning: /home/jan/src/swipl-devel/linux/s.pl:3:8: 
Warning:     format/3: Template requires 1 arguments, got 0
Warning: /home/jan/src/swipl-devel/linux/s.pl:4:8: 
Warning:     format/2: Template requires 0 arguments, got 1
% Checking redefined system and global predicates ...
% Checking predicates with declarations but without clauses ...
% Checking predicates that need autoloading ...
true.
4 Likes