June 27, 2013
On Wednesday, 26 June 2013 at 22:56:41 UTC, Walter Bright wrote:
> On 6/26/2013 2:47 PM, Paulo Pinto wrote:
>> 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.
>
> Even if you can get past the execrable look of it, it suffers from at least 3 terrible technical problems:
>
> 1. not thread safe
>
> 2. not exception safe
>
> 3. having to acquire/release mutexes for every << operation rather than once for the whole expression

Thanks for listing those issues they actually represent areas where I never used iostreams directly.

1. our iostream usage tends to be done from a central place

2. I am yet to write portable C++ code with exceptions turned on

3. wasn't aware of it

June 27, 2013
On Thursday, 27 June 2013 at 06:59:49 UTC, Jonathan M Davis wrote:
> 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.
>

I second Andrei on that one. It is useful in all cases string format is passed as argument/configuration/whatever.
June 27, 2013
On Wednesday, 26 June 2013 at 22:04:39 UTC, H. S. Teoh wrote:
> On Wed, Jun 26, 2013 at 11:47:32PM +0200, Paulo Pinto wrote:
>> Am 26.06.2013 20:52, schrieb H. S. Teoh:
> [...]
>> >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.
>
> They're ugly, that's why. :) And misleading to anyone familiar with bit
> operators.


You just have to get used to the concept that operators are just
abstract method names, like in abstract math.

Operators are method calls, never think of them as anything else.

This is no different from languages like Eiffel, Smalltalk and all
the others that allow special characters as method names.


>
> But that's beside the point. The main problem is that format strings are
> inadequately replaced by operator<< and its ilk; C++ tried to get around
> them by introducing the concept of manipulators and whatnot, but that
> only increased the ugliness of it all. Plus, it made a string of <<'s
> stateful, (if the previous line sends a manipulator to cout, then
> subsequent <<'s are subtly modified from their usual behaviour) making
> it harder to read.

Yeah, the state fulness is a bit verbose, but I can live with it.

>
> D's writefln is far superior to C's stdio and C++'s iostream, in any
> case.

Agreed.


>
>
>> But I try to keep my C++ code clean from C'isms anyway.
> [...]
>
> I tried doing that once. It was a rather painful experience. That's the
> problem with C++: it started out as being C + classes, but then wanted
> really badly to assume its own identity, so it accumulated a whole bunch
> of other stuff, but then it never really cut its ties with C, and the
> old C + classes heritage lives on. As a result, its OO system leaves a
> lot to be desired when compared with, say, Java, but using it for just C
> + classes seems underwhelming when there's so much more to the language
> than just that. So you end up in this limbo where it's more than C +
> classes, but doesn't quite make it to the level of real OO like Java,
> and lots of hacks and ugly corner cases creep in to try to hold the
> tower of cards together. Trying to be free of C'isms only exposed the
> flaws of C++'s OO system even more. I found that writing C + classes is
> still the least painful way to use C++.
>
> Fortunately, there's D to turn to. ;-)
>
>
> T

When I got to use C for the first time, back in 1992, I already knew a few Basic and Pascal dialects. So C felt really primitive with no added value over Object Pascal other than being more portable to systems I could not afford anyway.

The year thereafter I got my hands on Turbo C++ and then I found a world where I could have C's portability and with a bit of effort some of Pascal's safety back.

Since those days, I only touched C when required for university work and on my first job.

Nowadays it is mostly JVM/.NET at work, with alternative languages on my free time, including D. :)



--
Paulo

June 27, 2013
On Thursday, 27 June 2013 at 07:33:16 UTC, Paulo Pinto wrote:
> On Wednesday, 26 June 2013 at 22:56:41 UTC, Walter Bright wrote:
>> On 6/26/2013 2:47 PM, Paulo Pinto wrote:
>>> 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.
>>
>> Even if you can get past the execrable look of it, it suffers from at least 3 terrible technical problems:
>>
>> 1. not thread safe
>>
>> 2. not exception safe
>>
>> 3. having to acquire/release mutexes for every << operation rather than once for the whole expression
>
> Thanks for listing those issues they actually represent areas where I never used iostreams directly.
>
> 1. our iostream usage tends to be done from a central place
>
> 2. I am yet to write portable C++ code with exceptions turned on
>
> 3. wasn't aware of it

I *used* to like c++'s streams. Very recently, I did a project with high input output (not in terms of speed, but in terms of complexity), and it was *horrible!*

Streams have over fprints the ability to statically extract type, which is a win. However, it doesn't have format strings: What it has is global state, where it says "now I'm printing in hex", "now I'm printing with '0' as filler". "My next print will have 6 width"!

Long story short, to print a 2-width '0' padded hex, followed by a 4 width ' ' padded decimal takes some 120 characters, completely obliterating what the original string was about. Trying to re-read the damn thing is near impossible. If you are serious about your stream manipulation, it also means you should save the state of your stream before each write, and then restore it at the end of your write (or in your catch...)

IMO, the concept of manipulators and global state is plain retarded. It would have been better to have a stormat *object*, that references the object that needs to be passed, and then the stream handles the formated object printing. EG:

std::cout << "0x" << std::format(5).w(2).f('0').hex() << std::endl;

It is still a bit verbose, but very less so, and much less intrusive, and it keeps the formats tied to the object, rather than the stream.

Fun fact, this should actually be pretty easy to implement :D...
June 27, 2013
On Thursday, 27 June 2013 at 02:17:09 UTC, Andrei Alexandrescu wrote:
> On 6/26/13 1:31 PM, Andrej Mitrovic wrote:
>> On 6/26/13, Andrei Alexandrescu<SeeWebsiteForEmail@erdani.org>
>>  wrote:
>>> 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).
>>
>> Note that this works:
>>
>> writefln("%d", x, x);
>>
>> But the following throws since v2.061:
>>
>> writeln(format("%d", x, x));
>>
>> std.format.FormatException@C:\dmd-git\dmd2\windows\bin\..\..\src\phobos\std\string.d(2346):
>> Orphan format arguments: args[1..2]
>>
>> I find the latter to be quite useful for debugging code, and wanted
>> this feature for a long time.
>
> I think that's a bug in format that we need to fix.
>
> Andrei

I wanted to react on this: I'm surprised that writef and format *could* even have different behaviors (!) Don't both just forward to some sort of "format(sink, fmt, args...)" function that handles all the common code?

Or are there other subtle differences, bugs, where writef would produce different output from format?
June 27, 2013
On Wednesday, 26 June 2013 at 18:08:10 UTC, bearophile wrote:
[cut]
> The most common problem they find are errors in the format string of printf-like functions (despite the code is C++):
>
>>The top type of bug that /analyze finds is format string errors – mismatches between printf-style format strings and the corresponding arguments. Sometimes there is a missing argument, sometimes there is an extra argument, and sometimes the arguments don’t match, such as printing a float, long or ‘long long’ with %d.<
>
> Such errors in D are less bad, because writef("%d",x) is usable for all kind of integral values. On the other hand this D program prints just "10" with no errors, ignoring the second x:
>
> import std.stdio;
> void main() {
>     size_t x = 10;
>     writefln("%d", x, x);
> }
>
> In a modern statically typed language I'd like such code to give a compile-time error.

An even better thing would be to have a design which reduce a lot the probability of format string error, see Scala:

val name = "James"
println(s"Hello, $name")


renoX
June 27, 2013
On Wednesday, 26 June 2013 at 20:50:03 UTC, bearophile wrote:
> If you want a special behavour you should use a special function as partialWritefln that ignores arguments not present in the format string.

Or maybe just define a new format specifier (%z, for 'zap'?) to ignore one or more arguments?
June 27, 2013
Jonathan M Davis:

> Andrei Alexandrescu:
>> 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.

OK :-)

Bye,
bearophile
June 27, 2013
On Thursday, 27 June 2013 at 06:59:49 UTC, Jonathan M Davis wrote:
> But if we make a design decision that favors 1% of our userbase

I really think we all need to be more careful about these kinds of statements. I often see posts on the newsgroup where someone says "feature/function X is totally useless".... and it is something I actually use.

In this thread, there's I think three people who said the extra arguments are a good thing (myself, Andrei, and Peter). And there's what, maybe a dozen participants in the thread (I didn't count, I think it is less though)?

That's not a big enough sample to be statistically significant, but what are the odds that this thread is so skewed that only 1% of D's userbase feels this way, when 25% of the thread disagrees?
June 27, 2013
On 6/27/13, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> NO! This is exactly the kind of code that is buggy and useless. The right use cases involve more arguments than format specifiers.

I mistyped that, I meant:

format("%s", 1, 2);  // no exceptions in future release
safeFormat("%s", 1, 2);  // exception thrown
1 2 3 4 5 6 7 8