www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Two possibilities of fixing format problem, which is better?

reply berni44 <dlang d-ecke.de> writes:
This post is ab out issue 9592 [1], namely, that format does 
ignore the width parameter and the minus flag for some types and 
for some not (numbers, bool, strings). According to the 
documentation width is used always and the minus flag only for 
numbers.

Now I see two ways to fix this:

a) Correct the documentation.
b) Correct the code (in this case I'd change the documentation of 
the minus flag to include non-number types too).

What do you think is better?


[1] https://issues.dlang.org/show_bug.cgi?id=9592
[2] https://dlang.org/phobos/std_format.html#.formattedWrite
Oct 20
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 21/10/2019 6:55 AM, berni44 wrote:
 This post is ab out issue 9592 [1], namely, that format does ignore the 
 width parameter and the minus flag for some types and for some not 
 (numbers, bool, strings). According to the documentation width is used 
 always and the minus flag only for numbers.
 
 Now I see two ways to fix this:
 
 a) Correct the documentation.
 b) Correct the code (in this case I'd change the documentation of the 
 minus flag to include non-number types too).
 
 What do you think is better?
 
 
 [1] https://issues.dlang.org/show_bug.cgi?id=9592
 [2] https://dlang.org/phobos/std_format.html#.formattedWrite
What does printf do? That is your baseline.
Oct 20
parent reply berni44 <dlang d-ecke.de> writes:
On Sunday, 20 October 2019 at 23:15:28 UTC, rikki cattermole 
wrote:
 What does printf do?
b) :-) Thanks.
Oct 21
parent reply berni44 <dlang d-ecke.de> writes:
On Monday, 21 October 2019 at 07:18:09 UTC, berni44 wrote:
 On Sunday, 20 October 2019 at 23:15:28 UTC, rikki cattermole 
 wrote:
 What does printf do?
b) :-) Thanks.
Unfortunately, meanwhile I learned, that there are various implementations of printf with different behaviour. So it doesn't really answer my original question. Here an example: import std.stdio; int[] a = [1,23,-456]; writeln(format("%20s",a)); writeln(format("[%(%20s%|, %)]",a)); produces: [ 1, 23, -456] [ 1, 23, -456] but IMHO the first line should be: [1, 23, -456] This is in accordance with the current Phobos spec and some printf spec I found in the internet. Should this be corrected? Similar: import std.stdio; char[] a = ['a','b','c']; writeln(format("%20s",a)); writeln(format("[%(%20s%|, %)]",a)); produces: abc ['a', 'b', 'c'] And: import std.stdio; String[] a = ["a","b","c"]; writeln(format("%20s",a)); writeln(format("[%(%20s%|, %)]",a)); produces: ["a", "b", "c"] ["a", "b", "c"] So my question remains: What is considered correct behaviour here?
Oct 22
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Oct 22, 2019 at 04:34:52PM +0000, berni44 via Digitalmars-d wrote:
[...]
 import std.stdio;
 
 int[] a = [1,23,-456];
 writeln(format("%20s",a));
 writeln(format("[%(%20s%|, %)]",a));
 
 produces:
 
 [                   1,                   23,                 -456]
 [                   1,                   23,                 -456]
 
 but IMHO the first line should be:
 
        [1, 23, -456]
 
 This is in accordance with the current Phobos spec and some printf
 spec I found in the internet. Should this be corrected?
IMO, yes. When you write "%20s" you're essentially saying "format the next argument as a string with width 20". It's unexpected behaviour for the width to suddenly apply to elements within the object as opposed to the object itself. If somebody wants the 20 to apply to each element instead, then he should write the second format string as you showed above.
 Similar:
 
 import std.stdio;
 
 char[] a = ['a','b','c'];
 writeln(format("%20s",a));
 writeln(format("[%(%20s%|, %)]",a));
 
 produces:
 
                  abc
 ['a', 'b', 'c']
 
 And:
 
 import std.stdio;
 
 String[] a = ["a","b","c"];
 writeln(format("%20s",a));
 writeln(format("[%(%20s%|, %)]",a));
 
 produces:
 
 ["a", "b", "c"]
 ["a", "b", "c"]
 
 So my question remains: What is considered correct behaviour here?
IMO the 20 should apply to whatever object the next argument is *as a whole*, since that's the most useful and expected behaviour. It's unexpected for "%20s" to apply the 20 width to the entire object when the argument is a string, but suddenly changes to 20 width *per element* when the argument is an array that isn't a string. T -- There are three kinds of people in the world: those who can count, and those who can't.
Oct 22
parent reply berni44 <dlang d-ecke.de> writes:
On Tuesday, 22 October 2019 at 17:12:53 UTC, H. S. Teoh wrote:
 IMO, yes.  When you write "%20s" you're essentially saying 
 "format the next argument as a string with width 20". It's 
 unexpected behaviour for the width to suddenly apply to 
 elements within the object as opposed to the object itself.
While trying to implement this I came across a function called formatElement. Next to this there is a comment saying "undocumented because of deprecation". Does anyone know about this "deprecation" of formatElement? It's used inside std.format, e.g. for formating ranges. And it appears in one public example, where it probably should not appear. The reason I'm asking is, that I'd like to get the following unittest working: unittest { int[2] a = [-5, 345]; string t1 = format("[%10s] [%-10s]", a, a); assert(t1 == "[ [-5, 345]] [[-5, 345] ]"); } So far I managed to do this, but now an other unittest pops up, namely: formatTest( [cast(string)"hello"], `["hello"]` ); This is essentially, because the old implementation called formatElement, while the new one doesn't. Looking inside formatElement, this function formats the element not according to some %... parameter, but similar to how it would be presented as a litteral in source code. Now I'm unsure, how to continue.
Oct 23
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Oct 23, 2019 at 02:45:51PM +0000, berni44 via Digitalmars-d wrote:
 On Tuesday, 22 October 2019 at 17:12:53 UTC, H. S. Teoh wrote:
 IMO, yes.  When you write "%20s" you're essentially saying "format
 the next argument as a string with width 20". It's unexpected
 behaviour for the width to suddenly apply to elements within the
 object as opposed to the object itself.
While trying to implement this I came across a function called formatElement. Next to this there is a comment saying "undocumented because of deprecation". Does anyone know about this "deprecation" of formatElement?
git blame and git log --graph reveal that the "deprecation" came from Phobos PR #2890. Perhaps start by looking there? What I'd do is to checkout Phobos just before that PR merge and then do a further git blame / git log --graph to find when formatElement was changed before that. Hopefully the history of changes will help you piece together what exactly happened, and perhaps suggest some possible reasons why.
 It's used inside std.format, e.g. for formating ranges. And it appears
 in one public example, where it probably should not appear.
 
 The reason I'm asking is, that I'd like to get the following unittest
 working:
 
 unittest
 {
     int[2] a = [-5, 345];
     string t1 = format("[%10s] [%-10s]", a, a);
     assert(t1 == "[ [-5, 345]] [[-5, 345] ]");
 }
 
 So far I managed to do this, but now an other unittest pops up, namely:
 
 formatTest( [cast(string)"hello"], `["hello"]` );
 
 This is essentially, because the old implementation called
 formatElement, while the new one doesn't. Looking inside
 formatElement, this function formats the element not according to some
 %... parameter, but similar to how it would be presented as a litteral
 in source code.
 
 Now I'm unsure, how to continue.
I don't know the entire story behind this, but what I know is this: in certain cases, std.format was expected to format certain aggregates of strings such that each string was quoted. One case is string[], where the output was expected to be like this: ["abc", "def", ... ] rather than: [abc, def, ... ] Why, I'm not really sure, but later on the '-' flag was added to the %s specifier in order to get the second behaviour instead of the first (i.e., "%-s instead of %s"). Obviously, when this was done whoever did it wanted to maintain backward compatibility with the auto-quoting behaviour, so the second behaviour is not default, but you have to explicitly ask for it with the '-' flag. This is why in certain aggregate formats involving %(...%) I often find myself having to revise it to %-(...%) instead, just so the strings will show up correctly in the output. I'd suggest you try to maintain backward compatibility with this special case behaviour, if possible, so that existing codebases won't get a nasty surprise (suddenly quoted strings are no longer quoted in the output). AFAIK, this special-casing only applies to string elements; other types should be free of such odd behaviours. P.S. If it were up to me, I'd try to get rid of this awkward special case, but then I'm not exactly sure how one would go about deprecating a certain aspect of format strings, esp. since most older code use runtime format strings, so you can't get any warning until runtime, which is very bad for deprecations. T -- That's not a bug; that's a feature!
Oct 23