December 24, 2018
On Monday, 24 December 2018 at 18:10:16 UTC, H. S. Teoh wrote:
> On Mon, Dec 24, 2018 at 05:54:45PM +0000, 12345swordy via Digitalmars-d wrote:
>> On Monday, 24 December 2018 at 17:08:33 UTC, H. S. Teoh wrote:
>> > From what I understand, Walter dislikes implicit conversions because of the horrible mess in C++ caused by implicit conversions and the associated obfuscated tangle of rules that nobody except language lawyers would even begin to understand.
> [...]
>> I understand his concerns. However it doesn't change the fact that
>> people use alias this as way of implicit casting, and people desire
>> custom implicit conversions!
>> *** We can introduce implicit conversations without introducing the
>> mess that is C++!***
> [...]
>
> If you can convince him, that would be great!
>
>
> T

If I were to write a DIP on this, I have to wait to see if R-Values is going to be accepted or not.

Alex
December 24, 2018
On 12/24/2018 10:10 AM, H. S. Teoh wrote:
> If you can convince him, that would be great!

You'd need very compelling use cases.

It's like adding more and more horsepower to a car. At some point, it doesn't make the car better.

Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example,

* iostreams

* regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf

? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).
December 24, 2018
On Mon, Dec 24, 2018 at 11:57:50AM -0800, Walter Bright via Digitalmars-d wrote: [...]
> Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example,
> 
> * iostreams
> 
> * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf
> 
> ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).

Haha, I happen to have the same opinion on the above two examples as you do.

Iostream's (ab)use of << and >> contrary to their intended meaning is absolutely atrocious.  The wrong precedence of << and >> (as far as I/O is concerned) leads to required parentheses where you don't expect them, with odd results if you forget. And a readability nightmare when you need to output an integer shifted by some amount (which << is output and which is bit shift?).  Not to mention the whole hack on top of a patch on top of a festering bandage concept of I/O manipulators and other such "clever" ideas that focus on solving the wrong problem.  The whole thing is a code smell, IMNSHO. Back when I still wrote C++, I avoided iostream like the plague and stuck with cstdio where possible.  I've had to debug iostreams-based code before, and it made me cringe every time.

And the regex DSL is just ... wow. It takes operator overloading abuse to whole new levels never before imagined.  The "regexes" you write with this mess of a design resemble *nothing* like regexes, and had absolutely strange precedence rules due to the abuse of operators to mean things far removed from their usual meanings. And have you seen the error messages? Whoa. It's the epitome of everything that's wrong with C++. This kind of code is barely writable and basically unmaintainable. Two symptoms that point to fundamental problems in the whole design. D's std.regex.ctRegex, for all of its warts, lets you write things like:

	auto re = ctRegex!`(\w+)@((\w+)(\.(\w+))*)`;

while offering the same (arguably better) benefits. Try to write the equivalent with that horrible C++ regex library, and it becomes crystal clear that the D version got it right, warts aside.[1]

[1] (Like seriously, just last week I rewrote one of my programs to completely avoid std.regex, because the mere act of using a regex adds 5 *seconds* to the total compilation time. And it's not even a complicated regex to begin with. Though, to be fair, the fact that we're annoyed over seconds rather than minutes or, God forbid, hours, that would have been usual fare in complex C++ projects, is a testament to how far ahead D is in this respect, in spite of said warts.)

I've also worked with C++ libraries that overload the comma operator... Oh yes, the evil comma operator plus absolutely evil abuse of operator overloading. Oy.

This kind of every-man-for-himself operator overloading leads to unmaintainable code where any piece of syntax can mean absolutely *anything*, because you can overload anything and everything, and you cannot even remotely begin to guess what a piece of code actually does just by looking at it.  You might have had a fighting chance if you could only trace the calls to their call targets, but thanks to the lovely C++ blend of overload resolution rules, Koenig lookup, SFINAE, and implicit conversions, you need to be a language lawyer just to figure that out.

D got it right by restricting the overloading of <, >, ==, etc., to a couple of consistent functions, instead of C++'s encouraging abuse by allowing arbitrary, unrelated implementations of < and >, for example, while discouraging correct use by requiring excessive boilerplate to overload <, then >, then ==, then !=, then <= and >=, just to be sure you covered all the bases.

But I suppose we should count our blessings, that the iostream authors didn't choose to overload < and > for I/O instead of << and >> (which you absolutely could, if you're bent on writing bad code), so there remains something to be appreciated here, I guess.</sarcasm>


T

-- 
Skill without imagination is craftsmanship and gives us many useful objects such as wickerwork picnic baskets.  Imagination without skill gives us modern art. -- Tom Stoppard
December 24, 2018
On 12/24/2018 1:31 PM, H. S. Teoh wrote:

There are technical problems with iostreams as well, such as formatting options, and not being multi-threadable.


> And the regex DSL is just ... wow. It takes operator overloading abuse
> to whole new levels never before imagined.

I've talked to David Abrahams about it. It is a nice piece of engineering, and he's very proud of it. But I was right in my assessment of the abuse of operator overloading, as this sort of thing has just never caught on in the C++ community.

Another in the "too much power" category is you can throw any type in C++. Such as an `int`. I've never, ever seen any credible use of that. I'm not in the least surprised that the C++ standard library has an Exception class you're supposed to derive from and throw that.


> This kind of every-man-for-himself operator overloading leads to
> unmaintainable code where any piece of syntax can mean absolutely
> *anything*, because you can overload anything and everything, and you
> cannot even remotely begin to guess what a piece of code actually does
> just by looking at it.  You might have had a fighting chance if you
> could only trace the calls to their call targets, but thanks to the
> lovely C++ blend of overload resolution rules, Koenig lookup, SFINAE,
> and implicit conversions, you need to be a language lawyer just to
> figure that out.

Yeah, that about sums up my argument to David about it.


> But I suppose we should count our blessings, that the iostream authors
> didn't choose to overload < and > for I/O instead of << and >> (which
> you absolutely could, if you're bent on writing bad code), so there
> remains something to be appreciated here, I guess.</sarcasm>

I hated iostreams since the 1980s, but it took about 15 years for the C++ community to gradually come around to the idea that it was a mistake.

A feature shouldn't be merely "cool" or "great", especially considering all the features D already has. It needs to enable significantly better code to be written. Better as in more efficient, more understandable, safer, less brittle, less tendency for errors, etc. Note that I didn't say "less typing" (!).
December 24, 2018
On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:
> On 12/24/2018 10:10 AM, H. S. Teoh wrote:
>> If you can convince him, that would be great!
>
> You'd need very compelling use cases.
>
> It's like adding more and more horsepower to a car. At some point, it doesn't make the car better.
>
> Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example,
>
> * iostreams
>
> * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf
>
> ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).

A use case that pops in my head is to avoiding using inheritance as that is not always ideal tool, when it comes to structs/class as you have no control on how it does implicit conversions.
No Basic Event programming.
No Design by Introspection.
No Data Conversion in Regards to Passing Member Variables.
You class/struct may end up with functions/variables that you don't want, which creates needless bloat.
If you want to support multiple implicit conversion with the current features, then you need multiple alias this, which is not a good solution as
A.) It is multiple inheritance. Which we both agree it is a terrible idea.
B.) Multi alias this still hasn't been implemented already. *Throws table*

December 24, 2018
On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:
> On 12/24/2018 10:10 AM, H. S. Teoh wrote:
>> If you can convince him, that would be great!
>
> You'd need very compelling use cases.
>
> It's like adding more and more horsepower to a car. At some point, it doesn't make the car better.
>
> Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example,
>
> * iostreams
>
> * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf
>
> ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).

Oh btw Merry Christmas!

Alex
December 24, 2018
On Mon, Dec 24, 2018 at 02:30:57PM -0800, Walter Bright via Digitalmars-d wrote:
> On 12/24/2018 1:31 PM, H. S. Teoh wrote:
[...]
> > And the regex DSL is just ... wow. It takes operator overloading abuse to whole new levels never before imagined.
> 
> I've talked to David Abrahams about it. It is a nice piece of engineering, and he's very proud of it. But I was right in my assessment of the abuse of operator overloading, as this sort of thing has just never caught on in the C++ community.

Ah well, just because something is a nice piece of engineering, doesn't necessarily mean it was a good idea in the first place!


> Another in the "too much power" category is you can throw any type in C++.  Such as an `int`. I've never, ever seen any credible use of that. I'm not in the least surprised that the C++ standard library has an Exception class you're supposed to derive from and throw that.

I used to have a code library that standardized on throwing char* to string literals. It was a lazy man's way of having error messages that masqueraded as error codes / exceptions.  Not my proudest moment of software design. :-D

Though I'll say that the primary motivation for that was my C background, where everything is an int error code, and my being utterly fed up with code that just returned a non-descript -1 on every kind of failure, or worse, returning the return value of another function that returns an *incompatible* range of int error codes, in a totally inconsistent way (e.g., sometimes the function would return -1, or ERR_XYZ where ERR_* is a series of error codes defined in module A, and sometimes returning errno, which is incompatible with module A's error codes, all jammed into a single int return that the caller could not possibly hope to unambiguously decipher).  Worst of all, when a problem occurred I'd get a message like "error -123" with zero hint as to what -123 even means.  Having char* as an error code instead ensured (1) there's always a human-readable message you can get out of it, even if you couldn't otherwise interpret it; (2) since char* is unique in the space of string literals, you can freely mix error code returns and not have to worry about ambiguities (the dynamic linker will even "remap error codes" for you so errors from multiple libraries will never be confused for one another); (3) no memory allocation is needed -- at least if you stick to my scheme of returning only string literals.

Of course, there are other issues with such a design, but it seemed like a good idea at the time.


[...]
> > But I suppose we should count our blessings, that the iostream authors didn't choose to overload < and > for I/O instead of << and
> > >> (which you absolutely could, if you're bent on writing bad code), so there remains something to be appreciated here, I guess.</sarcasm>
> 
> I hated iostreams since the 1980s, but it took about 15 years for the C++ community to gradually come around to the idea that it was a mistake.

I haven't been keeping up with C++ in any serious way ever since I found D; what's the replacement for iostreams these days?  Or is it yet another one of those Irreversible Historical Accidents that's here to stay, in spite of acknowledged flaws, to be patched over by Yet More Language Complications that will make the language require a PhD specializing in C++ just so you can write correct code, since the "obvious" way to write C++ is wrong in more ways than you even knew existed?


> A feature shouldn't be merely "cool" or "great", especially considering all the features D already has. It needs to enable significantly better code to be written. Better as in more efficient, more understandable, safer, less brittle, less tendency for errors, etc. Note that I didn't say "less typing" (!).

Unfortunately, all of those points conflict with each other at some level, and it's not immediately obvious which blend of them represents the best balance.


T

-- 
VI = Visual Irritation
December 24, 2018
On 12/24/2018 3:24 PM, H. S. Teoh wrote:
> I haven't been keeping up with C++ in any serious way ever since I found
> D; what's the replacement for iostreams these days?

Not that I'm aware of. Of course, like C's gets(), it'll never go away.

December 24, 2018
On Monday, 24 December 2018 at 23:06:26 UTC, 12345swordy wrote:
> On Monday, 24 December 2018 at 19:57:50 UTC, Walter Bright wrote:
>> On 12/24/2018 10:10 AM, H. S. Teoh wrote:
>>> If you can convince him, that would be great!
>>
>> You'd need very compelling use cases.
>>
>> It's like adding more and more horsepower to a car. At some point, it doesn't make the car better.
>>
>> Or like operator overloading. C++ has much more expansive rules for operator overloading. They lead to clever programs, and some people swear by them, but are they *better* programs? For example,
>>
>> * iostreams
>>
>> * regex DSL https://pdfs.semanticscholar.org/e630/5f84bca36251fd5a4ffa5f00e0effc8aaa7d.pdf
>>
>> ? I don't buy it. I've never seen an elegant use of the more expansive power (even though many insist those two examples are elegant).
>
> A use case that pops in my head is to avoiding using inheritance as that is not always ideal tool, when it comes to structs/class as you have no control on how it does implicit conversions.

When talking implicit conversion (at least in the same sense as C++) you create a new object when doing an implicit conversion. How do you envision the implicit conversion would work?

> No Basic Event programming.

Why do you need implicit conversion for this ?

> No Design by Introspection.
> No Data Conversion in Regards to Passing Member Variables.
> You class/struct may end up with functions/variables that you don't want, which creates needless bloat.

You could just use explicit conversion for this, if that's the case. Other than not having write 1 extra identifier there wouldn't be that much more benefit.

> If you want to support multiple implicit conversion with the current features, then you need multiple alias this, which is not a good solution as
> A.) It is multiple inheritance. Which we both agree it is a terrible idea.
> B.) Multi alias this still hasn't been implemented already. *Throws table*

Idk, all this seems shakey. I avoid implicit conversion as much as possible in C++, the times I do use it usually is because of some other limitation in C++ that can be solved a different way in D. Some concrete examples would help though.

December 24, 2018
On Mon, Dec 24, 2018 at 03:28:08PM -0800, Walter Bright via Digitalmars-d wrote:
> On 12/24/2018 3:24 PM, H. S. Teoh wrote:
> > I haven't been keeping up with C++ in any serious way ever since I found D; what's the replacement for iostreams these days?
> 
> Not that I'm aware of. Of course, like C's gets(), it'll never go
> away.

So you're saying that basically my unpopular/unconventional choice of sticking with cstdio all these years was actually the right one?! Scary.


T

-- 
Answer: Because it breaks the logical sequence of discussion. / Question: Why is top posting bad?