June 27, 2013
On 27/06/13 14:20, H. S. Teoh wrote:
> On Thu, Jun 27, 2013 at 01:56:31PM +1000, Peter Williams wrote:
> [...]
>> While you're fixing it can you modify it so that the format string
>> can specify the order in which the arguments are replaced?  This is
>> very important for i18n.  I apologize if it can already do this but
>> I was unable to find any documentation of format()'s format string
>> other than examples with %s at the appropriate places.
> [...]
>
> You can use positional arguments for this purpose. For example:
>
> 	writefln("%2$s %1$s", "a", "b");
>
> outputs "b a".

Yes, I eventually found the documentation in std.format while I expected it to be in std.string along with the documentation the format() function.  A reference to std.format in the documentation for format() (in std.string) would be nice.

Peter

June 27, 2013
On 6/26/13 8:05 PM, Andrej Mitrovic wrote:
> If you are the type of programmer who often tests their own code, why
> are you passing more arguments than needed to format?

My point is they're needed.

Andrei
June 27, 2013
On 6/26/13 8:26 PM, Andrej Mitrovic wrote:
> The way I see it, write/writef is primarily used for debugging and
> benefits having some lax features, whereas format is used in more
> heavy-duty work where it's important not to screw things up at the
> call site.

Then I think all the more format should allow more arguments than format specifiers. That does help serious use.

> But the bottom line is I don't think we need to force anything on
> anybody. If anything, we could split up the internal format
> implementation and provide format and safeFormat functions.
>
> format("%s %s", 1);  // no exceptions

NO! This is exactly the kind of code that is buggy and useless. The right use cases involve more arguments than format specifiers.


Andrei
June 27, 2013
On 6/26/13 8:36 PM, Jonathan M Davis wrote:
> On Wednesday, June 26, 2013 19:18:27 Andrei Alexandrescu wrote:
>> On 6/26/13 1:50 PM, bearophile wrote:
>>> Andrei Alexandrescu:
>>>> Actually this is good because it allows to customize the format string
>>>> to print only a subset of available information (I've actually used
>>>> this).
>>>
>>> Your use case is a special case that breaks a general rule.
>>
>> There's no special case here.
>
> I have never heard anyone other than you even suggest this sort of behavior.
> Granted, I may just not talk with the right people, but that at least makes it
> sound like what you're suggesting is a very special case.

I'm not surprised. Not many people deal with things like localization or internalization.

>>> That
>>> behavour is surprising, and it risks hiding some information silently.
>>
>> Doesn't surprise me one bit.
>
> Well, it shocks most of us.

I'm also not moved by argumentum ad populum.

> We expect the number of arguments to a function to
> match the number of parameters, and with format strings, you're basically
> declaring what the parameters are, and then the other arguments to format or
> writefln are the arguments to the format string. Most of us don't even think
> about swapping out the format string at runtime.

That is the smoking gun.


Andrei

June 27, 2013
On 6/26/13 10:35 PM, Peter Williams wrote:
> On 27/06/13 14:20, H. S. Teoh wrote:
>> On Thu, Jun 27, 2013 at 01:56:31PM +1000, Peter Williams wrote:
>> [...]
>>> While you're fixing it can you modify it so that the format string
>>> can specify the order in which the arguments are replaced? This is
>>> very important for i18n. I apologize if it can already do this but
>>> I was unable to find any documentation of format()'s format string
>>> other than examples with %s at the appropriate places.
>> [...]
>>
>> You can use positional arguments for this purpose. For example:
>>
>> writefln("%2$s %1$s", "a", "b");
>>
>> outputs "b a".
>
> Yes, I eventually found the documentation in std.format while I expected
> it to be in std.string along with the documentation the format()
> function. A reference to std.format in the documentation for format()
> (in std.string) would be nice.

The only point I'd negotiate would be to not throw with positional arguments, and throw with sequential arguments. All code that cares uses positional specifiers anyway.

Andrei
June 27, 2013
On Wednesday, June 26, 2013 23:49:41 Andrei Alexandrescu wrote:
> The only point I'd negotiate would be to not throw with positional arguments, and throw with sequential arguments. All code that cares uses positional specifiers anyway.

That sounds like a good compromise.

- Jonathan M Davis
June 27, 2013
On Wednesday, June 26, 2013 23:47:15 Andrei Alexandrescu wrote:
> >>> That
> >>> behavour is surprising, and it risks hiding some information silently.
> >> 
> >> Doesn't surprise me one bit.
> > 
> > Well, it shocks most of us.
> 
> I'm also not moved by argumentum ad populum.

ad populum obviously isn't enough. But if we make a design decision that favors 1% of our user base and causes problems for the other 99%, then I think that we've made a big mistake. And while having most everyone disagree with one person does not make that person wrong, it _does_ make it more likely that they're wrong. So, while ad populum should not be the sole reason to make a decision, I think that it's generally a bad idea to ignore it. I'm not trying to say anything about this particular discussion and whether we should go with the majority on this; I'm just pointing out that ignoring what the majority thinks is not necessarily a good idea.

- Jonathan M Davis
June 27, 2013
On 6/26/13 11:59 PM, Jonathan M Davis wrote:
> On Wednesday, June 26, 2013 23:47:15 Andrei Alexandrescu wrote:
>>>>> That
>>>>> behavour is surprising, and it risks hiding some information silently.
>>>>
>>>> Doesn't surprise me one bit.
>>>
>>> Well, it shocks most of us.
>>
>> I'm also not moved by argumentum ad populum.
>
> ad populum obviously isn't enough. But if we make a design decision that
> favors 1% of our user base and causes problems for the other 99%

My point is it doesn't cause any problem except for the 0.0001% who refuse to even take ONE look at the output of the format.

Andrei
June 27, 2013
On 6/26/13 11:59 PM, Jonathan M Davis wrote:
> I'm just pointing out that ignoring what the majority
> thinks is not necessarily a good idea.

Of course. In this case it is.

Andrei
June 27, 2013
On Thursday, 27 June 2013 at 02:25:54 UTC, Andrei Alexandrescu wrote:
> On 6/26/13 2:47 PM, Paulo Pinto wrote:
>> Am 26.06.2013 20:52, schrieb H. S. Teoh:
>>> On Wed, Jun 26, 2013 at 08:08:08PM +0200, bearophile wrote:
>>>> An interesting blog post found through Reddit:
>>>>
>>>> http://randomascii.wordpress.com/2013/06/24/two-years-and-thousands-of-bugs-of-/
>>>>
>>> [...]
>>>> The most common problem they find are errors in the format string of
>>>> printf-like functions (despite the code is C++):
>>>
>>> None of my C++ code uses iostream. I still find stdio.h more comfortable
>>> to use, in spite of its many problems. One of the most annoying features
>>> of iostream is the abuse of operator<< and operator>> for I/O. Format
>>> strings are an ingenious idea sorely lacking in the iostream department
>>> (though admittedly the way it was implemented in stdio is rather unsafe,
>>> due to the inability of C to do many compile-time checks).
>>
>> I have been an adept of iostreams since day one and never understood why
>> people complain so much about them or the operator<< and operator>>
>> for that matter.
>
> The problems with C++ iostreams are well-known and pernicious:
>
> 1. Extremely slow by design.
>
> 2. Force mixing representation with data by design
>
> 3. Keep conversion state within, meaning they force very bizarre tricks even for simple things such as printing/scanning hex numbers.
>
> 4. Approach to exception safety has the wrong default.
>
> 5. Approach to internationalization (locales) has the most byzantine design I've ever seen. Even people who took part to the design can't figure it all out.
>
>
> Andrei

I always liked their OO model and for the type of applications we use performance never was a problem.

My iostreams experience is mostly coupled to serialization of data structures, simple console applications.

Exception safety might be an issue, sadly I was never able to write portable C++ code at work that used either RTTI or exceptions. Just too many issues, which always lead to the architects forbidding their use.

Thanks for the explanation.

--
Paulo