September 30, 2016
On Friday, 30 September 2016 at 00:50:54 UTC, Jonathan M Davis wrote:
> Except that it kind of is. It's an example of a language allowing you to mess with too much and make it so that it doesn't function as expected, which is what happens when you overload operators to act in a way inconsistent with how they work with the built-in types.

Which language is more widely used? D or Perl?

Let me see if I understand your argument: We can't make D more expressive because a language far more popular than D is so expressive it makes it possible to do unconventional things, if you are so inclined?

September 30, 2016
On Friday, 30 September 2016 at 00:50:54 UTC, Jonathan M Davis wrote:
>
> Except that it kind of is. It's an example of a language allowing you to mess with too much and make it so that it doesn't function as expected, which is what happens when you overload operators to act in a way inconsistent with how they work with the built-in types. The perl example is more extreme, but the point still stands that having normal, common constructs operate in a way that's inconsistent with how they normally work tends to make code harder to read and maintain. Certainly, it can result in very unexpected behavior when mixing it with generic code that uses those operations.
>
> - Jonathan M Davis

It's up to the developer to ensure that their code works correctly with existing facilities, not the language. I can already write code that will work in amazing and ridiculous ways with generic code in the standard library. It does not follow that the language is responsible or at fault for the code behaving in ways that are unexpected.

Furthermore, it's completely reasonable to write code that works with the generic facilities in the standard library, even if it doesn't behave exactly like a built in type.

ie.

  foo.reduce!"a + b"; // => produces an integer
  bar.reduce!"a + b"; // => produces an AST node

So long as the types produced by the operation are correct, this will work just fine.
September 30, 2016
On Friday, September 30, 2016 09:55:36 pineapple via Digitalmars-d wrote:
> On Friday, 30 September 2016 at 00:50:54 UTC, Jonathan M Davis
>
> wrote:
> > Except that it kind of is. It's an example of a language allowing you to mess with too much and make it so that it doesn't function as expected, which is what happens when you overload operators to act in a way inconsistent with how they work with the built-in types.
>
> Which language is more widely used? D or Perl?
>
> Let me see if I understand your argument: We can't make D more expressive because a language far more popular than D is so expressive it makes it possible to do unconventional things, if you are so inclined?

perl is always widely considered to be a horrible language even if it is useful. And the example that was given for what you can do with perl is pretty insane.

Regardless, D already has a lot of powerful stuff in it, much of which will allow you to blow your foot off if you're really inclined to. The overloaded operators just so happened to be implemented in a way that doesn't let you blow your feet off as freely as C++'s overloaded operators will let you do.

- Jonathan M Davis

September 30, 2016
On Friday, September 30, 2016 12:31:45 Minty Fresh via Digitalmars-d wrote:
>
> It's up to the developer to ensure that their code works correctly with existing facilities, not the language. I can already write code that will work in amazing and ridiculous ways with generic code in the standard library. It does not follow that the language is responsible or at fault for the code behaving in ways that are unexpected.

Of course, you can write code that behaves badly. There's no way that that can be completely prevented while still allowing you to do useful, productive things. But the folks asking to be able to overload < separately just so that they can make it behave differently than what opCmp does are basically asking for a way to be allowed to make their code behave badly with the comparison operators in a way that opCmp doesn't currently allow. The request is to improve support for an idiom that many consider to be horrible coding practice, and Walter does not think that explicitly supporting such an idiom makes any sense.

He hasn't gone to extra effort to prevent every possible misuse of overloaded operators that he could. He simply defined some of the overloaded operators in a way that was a significant improvement for the use case that he thought that overloaded operators should be used for, and as a side effect, it happens to have made it harder for a use case that he thinks is bad practice. I think that he made the right decision.

But if you or anyone else wants to do wacky stuff with overloaded operators that is not consistent with the built-in types, you're free to do so within how D's overloaded operators work. You're just not going to be able to do it as freely as you can in C++, because that goes against the goals of the operator overloading feature in D, and some of the improvements that were in line with the goals happen to have gotten in the way of such operator overloading abuse.

- Jonathan M Davis

September 30, 2016
On 30.09.2016 03:15, Chris Wright wrote:
> On Thu, 29 Sep 2016 10:41:38 +0200, Timon Gehr wrote:
>
>> On 29.09.2016 06:15, Walter Bright wrote:
>>> On 9/28/2016 1:40 PM, Timon Gehr wrote:
>>>> (This is NOT expression templates.)
>>>
>>> Right, but it's an enabler of expression templates. Discussion of more
>>> powerful operator overloading cannot be divorced from expression
>>> templates, and once ETs are in we'll be stuck with them forever.
>>> ...
>>
>> They work today, just not with comparison operators.
>
> To take it the other way, D could enforce that the return type of
> arithmetic operators is compatible with at least one of the operands --
> by implicit cast or constructor or being the same type.


It wouldn't infer with any of my use cases, but I don't see the point.

> Wouldn't that be fun?
>

Certainly.
September 30, 2016
On 30.09.2016 18:11, Jonathan M Davis via Digitalmars-d wrote:
> Regardless, D already has a lot of powerful stuff in it, much of which will
> allow you to blow your foot off if you're really inclined to. The overloaded
> operators just so happened to be implemented in a way that doesn't let you
> blow your feet off as freely as C++'s overloaded operators will let you do.


OTOH, feet are useless if you are not allowed to walk (even if you choose not to blow them off).
September 30, 2016
On 30.09.2016 21:02, Timon Gehr wrote:
> On 30.09.2016 03:15, Chris Wright wrote:
>> ...
>
>> Wouldn't that be fun?
>>
>
> Certainly.

On a related note:

alias Seq(T...)=T;

struct S{
    int x;
    S opBinary(string op:"+",T...)(T args){
        S r=this;
        foreach(a;args) r.x+=a;
        return r;
    }
}

void main(){
    import std.stdio;
    assert(S(1) + Seq!(2,3,4) == S(10));
}

September 30, 2016
On Friday, 30 September 2016 at 16:25:45 UTC, Jonathan M Davis wrote:
> But if you or anyone else wants to do wacky stuff with overloaded operators that is not consistent with the built-in types, you're free to do so within how D's overloaded operators work. You're just not going to be able to do it as freely as you can in C++, because that goes against the goals of the operator overloading feature in D, and some of the improvements that were in line with the goals happen to have gotten in the way of such operator overloading abuse.

In your arguments in favor of this limitation of operator overloading, you keep referring to these goals, of what operator overloads have been intended to do. You've stated and restated that same explanation even though it's completely unconvincing because while stating this intention you have failed entirely to justify it.

How many people have to state it how many times in how many different ways before it gets through? These are stupid goals. They reflect intention that has no basis in reason, that has no basis in reality, that is a blindly-enforced dogma.

It always would have been simpler if, in the first place, opBinary had caught comparison operators and opCmp and opEquals were omitted. Instead, those making the decisions went out of their way to impose these arbitrary limitations. If we can start now to untangle that mistake, it will make D more tenable for real-world code.

And make no mistake: Perl is fantastic for real-world code because real-world code is not elegant, and it doesn't follow the rules, and it doesn't care how you meant for a feature to be used. Practical languages give the programmer a great deal of expressive power, and it's okay if the rules allow nonsense expressions because it's up to the programmer, not the language, to know what's nonsense and what's not.

September 30, 2016
On Friday, 30 September 2016 at 01:07:49 UTC, Chris Wright wrote:
> The perl example is a line of code buried somewhere that changes the meaning of the rest of the code. Operator overloading is restricted to a specific user-defined type. With such a dramatic difference in the scope of the change, the analogy is useless.

I was responding to someone that wrote: "I also have the presence of mind to recognize that my opinions are not universal, and they are certainly no basis for imposing arbitrary limits upon another person's behavior". I gave an example of what happens when you don't want "arbitrary limits".

Claiming that operator overloading only applies to a specific user-defined type makes it worse. Having it work one way for three types, a different way for four other types, and a third way for yet another type doesn't sound like a minor thing.

But have fun debating design decisions that were made long ago and aren't going to change.
September 30, 2016
On Friday, 30 September 2016 at 19:46:35 UTC, bachmeier wrote:
> Claiming that operator overloading only applies to a specific user-defined type makes it worse. Having it work one way for three types, a different way for four other types, and a third way for yet another type doesn't sound like a minor thing.

But operators already behave in different way for different types. Built-in types inclusive. The most trivial and nit-picky difference would be between integer types and floating point types.

ie. Division between two integers yields an integer, division between two floats yields a float, but then division between an integer and a float also yields a float.
Alternatively, the bit-shift operators `<<` and `>>` don't function at all for floats.
But then we have also wonderful floating point values like `NaN` and `Infinity` for which arithmetic and relational operators behave differently altogether.

Another would static arrays, versus dynamic arrays, versus associative arrays. The first two support concatenation via `~`, only the second supports in-place concatenation `~=`, and the last has no notion of concatenation at all.

A counter argument that might be raised is that those are different types altogether. They are intended to behave in different ways entirely. Completely different data structures. Their similarities are only superficial.

And such a counter argument would be absolutely correct. Markedly so. They are completely different types.
The same is true of user-defined types. Their behavior should not be equated to (nor expected to be like) the behaviors of types they only resemble superficially.

> But have fun debating design decisions that were made long ago and aren't going to change.

That's exactly the kind of decision making you see in C++ and PHP. Metathesiophobia would be one way of describing it. Stubborn blindness to real world usage is more contextually appropriate though, I feel.