September 28, 2016
On 28.09.2016 22:16, Walter Bright wrote:
> On 9/28/2016 6:58 AM, Timon Gehr wrote:
>>> An excellent example of that is the std.regex package.
>> It's actually a bad example, because it is irrelevant: it is obviously
>> a bad
>> idea to implement regex using operator overloading, because the regex
>> operators
>> have no D equivalent.
>
> Yet this "obviously bad" idea regularly resurfaces as a cool use of
> expression templates and respected people in the industry like it and
> advocate it.
> ...

This is not surprising. C++ has no good options.

>
>> Assume I have two symbolic expressions a and b:
>>
>> Expression a=variable("a"), b=variable("b");
>>
>> Why should I be allowed to do
>>
>> auto c = a + b; // symbolic value a + b
>>
>> but not
>>
>> auto d = a <= b; // symbolic value a <= b
>
> Because there is no way to stop the former but still have operator
> overloading.
> ...

What's wrong with that usage? (This is NOT expression templates.)

>
>> The string parsing approach is not useful here: how do I use existing
>> expressions that are accessible in the scope to build new expressions?
>
> You seem to be asking for expression templates.

No. It's symbolic computation at run time. Think Wolfram Mathematica.
September 28, 2016
On Wednesday, 28 September 2016 at 20:40:49 UTC, Timon Gehr wrote:
> This is not surprising. C++ has no good options.

This is further made worse by some C++'s more inane design decisions (ie. allowing overloading of the comma operator).
September 28, 2016
On 9/28/2016 1:40 PM, Timon Gehr wrote:
> What's wrong with that usage?

Because then something other than comparison is happening with <=, <, >, >= and there'll be nothing in the code to give the user a hint.


> (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.


D has many very powerful modeling abilities, but so far we've tried to stay away from things that make context-free user understanding of code unduly difficult. It should not be necessary to use an IDE to understand code.

In that category are things like text macros, AST macros, user-defined syntax, non-arithmetic operator overloading, and expression templates.
September 29, 2016
On Thursday, 29 September 2016 at 04:15:32 UTC, Walter Bright wrote:
> On 9/28/2016 1:40 PM, Timon Gehr wrote:
>> What's wrong with that usage?
>
> Because then something other than comparison is happening with <=, <, >, >= and there'll be nothing in the code to give the user a hint.

There's also nothing to give the user a hint that binary arithmetic operators may also not do what they expect them to do.
Going further, there may be nothing to give the user a hint that a named function doesn't to what its name suggests.

All of the above are shortcomings in documentation, or short comings in implementation.

Even with the current system of using `opCmp`, it's still possible to implement these operators such that they behave in a way that would confound the user (ie. have their results be nondeterministic, external side effects, etc.)

> D has many very powerful modeling abilities, but so far we've tried to stay away from things that make context-free user understanding of code unduly difficult. It should not be necessary to use an IDE to understand code.

No, you're right. It's not the responsibility of the IDE to perform such tasks. It's the responsibility of the documentation. D is already is such a state the language is difficult for a context-free user without access to documentation.

Even the standard library. Especially the standard library.
Things like `.each` in std.algorithm returning void, whereas the bizarrely named `.tee` in std.range actually retuning the input range. Things like the `SList` and `DList` types defined in std.container requiring explicit initialization to work. Things like the behavior and semantics of type tuples (or alias lists). Things like the differences between `.byLine` vs `.byLineCopy` in std.stdio.
All of these rely on the developer having documentation. There's no way around it. D as a language is already way too complex to do anything without it.

This applies to operator overloads just like everything else. They're just syntactic sugar for functions. Documenting their behavior is just as necessary.
September 29, 2016
On Thursday, 29 September 2016 at 04:39:37 UTC, Minty Fresh wrote:

>
> This applies to operator overloads just like everything else. They're just syntactic sugar for functions. Documenting their behavior is just as necessary.

I disagree with this. Operators are different in that the symbols themselves already have meaning and are a core part of the language. When I see a function in code that was written by someone else, I have no idea what it really does, no matter how it was named, until I pull up the documentation or the source and actually read it. I expect that I'm going to have to do that. Using operators in ways they were not intended to be used is breaking my expectations.

When I'm scanning D code and see a '+', I'm going to think addition (and not concatenation or appending or anything else). It isn't going to occur to me that the types involved are doing something completely different and I ought to look in the documentation to see what that is. And I shouldn't have to worry about it. That sort of cognitive disruption is really annoying.

In D1, operators were overloaded *by name* and not by symbol. I loved that, because it made it quite clear that opAdd is an addition and doing something different with it would be akin to having a function named printFoo launching an audio player. And if printFoo *did* launch an audio player, I'm quite confident most programmers would consider the function horribly misnamed. The same applies to operators, as I see it.
September 28, 2016
On Wednesday, September 28, 2016 21:15:32 Walter Bright via Digitalmars-d wrote:
> Because then something other than comparison is happening with <=, <, >, >= and there'll be nothing in the code to give the user a hint.
[snip]
> D has many very powerful modeling abilities, but so far we've tried to stay away from things that make context-free user understanding of code unduly difficult. It should not be necessary to use an IDE to understand code.

A related issue is generic code. Having the same operator or function name mean essentially the same thing for every type that has it is required for generic code to work. To some extent, that's also checked by having the semantics of the code checked (e.g. that front returns something as opposed to being void or that popFront takes no arguments), but there's only so much that can be done there. And no, even then, you can't guarantee that the function in question operates the way that the generic code expects. But if common function names mean the same thing and act the same way for types in general, then they play well with generic code, whereas as soon as someone takes a common function and makes it do something different from what's normal, it does not play well with generic code at all.

Overloaded operators are the prime example of this, because there is a clear expectation for what their basic behaviors are, and they're functions that are built into the language. Next in line would be extremely common idioms such as the range-based functions. Once you start getting to less common stuff, then the issue of whether a function with a particular name acts the same way in one library as another is significantly diminished, but for the common stuff, it's critical for generic code that folks don't go and make common functions operate in a way that is inconsistent with how they would function on most every other type out there and how everyone is going to expect them to behave when they see them.

Having a type implement something like expression templates is an utter disaster for generic code, just like it's a disaster if front does something like call popFront every time that it's called. Consistent semantics for common functions is very important for generic code as well as for code legibility and maintainability.

- Jonathan M Davis

September 29, 2016
On 2016-09-28 06:02, Walter Bright wrote:

> The limitations are deliberate based on the idea that comparison
> operators need to be consistent and predictable, and should have a close
> relationship to the mathematical meaning of the operators. Overloading
> <= to mean something other than "less than or equal" is considered poor
> style in D, and the same goes for the other arithmetic operators.

If that is not allowed, why is this allowed:

struct MyInt
{
    int value;

    MyInt opBinary(string op)(MyInt rhs) if (op == "+")
    {
        return MyInt(value - rhs.value);
    }
}

assert(MyInt(3) + MyInt(3) == MyInt(0));

The language you just provide a set of tools, then it's up the to the programmer to do what he/she wants to do.

> The use of them to create DSLs (a technique called "expression
> templates" in C++) is discouraged in D, for several reasons. The
> recommended way to create DSLs in D is to parse strings using CTFE.

That's one of the ugliest things about D. Because suddenly you will not have any help of any tools, like editors, IDEs, linters, syntax analysis and so on. One also needs to implement a complete parser, how many complete parsers do we have for D?

-- 
/Jacob Carlborg
September 29, 2016
On 9/28/2016 11:48 PM, Jacob Carlborg wrote:
> If that is not allowed, why is this allowed:

I.e. you can overload '+' to do bad things. Yes, you can, and as I replied upthread that can be done because there's no way to prevent that while having operator overloading at all.

But that is not justification for allowing such disasters for the comparison operators. I.e. one weakness is not justification for opening the door to all weakness.

Interestingly, by shutting the door on misuse of the comparison operators, it seems D has been successful in discouraging nutburger designs like overloading '+' to mean 'OR'.


> The language you just provide a set of tools, then it's up the to the programmer
> to do what he/she wants to do.

That can be used to justify any feature at all.


>> The use of them to create DSLs (a technique called "expression
>> templates" in C++) is discouraged in D, for several reasons. The
>> recommended way to create DSLs in D is to parse strings using CTFE.
>
> That's one of the ugliest things about D. Because suddenly you will not have any
> help of any tools, like editors, IDEs, linters, syntax analysis and so on. One
> also needs to implement a complete parser, how many complete parsers do we have
> for D?

I know you really want AST macros for D. We've discussed that at length before.

BTW, there's a CTFE parser generator for D around somewhere.
September 29, 2016
On 29.09.2016 06:15, Walter Bright wrote:
> On 9/28/2016 1:40 PM, Timon Gehr wrote:
>> What's wrong with that usage?
>
> Because then something other than comparison is happening with <=,

You also complained about '+'.

> <, >,
>>= and there'll be nothing in the code to give the user a hint.
> ...

Actually, comparison is precisely what is happening. The hint about what is happening precisely is that the entire codebase does symbolic computations all over the place, and it is very clear what the involved types are.

>
>> (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.

>
> D has many very powerful modeling abilities, but so far we've tried to
> stay away from things that make context-free user understanding of code
> unduly difficult. It should not be necessary to use an IDE to understand
> code.
> ...

That is and has always been the responsibility of the programmer. (IDEs don't even help that much.)

> In that category are things like text macros, AST macros, user-defined
> syntax, non-arithmetic operator overloading, and expression templates.

What's the definition of "arithmetic" here?
September 29, 2016
On Thursday, 29 September 2016 at 07:58:26 UTC, Walter Bright wrote:
> On 9/28/2016 11:48 PM, Jacob Carlborg wrote:
>> If that is not allowed, why is this allowed:
>
> I.e. you can overload '+' to do bad things. Yes, you can, and as I replied upthread that can be done because there's no way to prevent that while having operator overloading at all.
>
> But that is not justification for allowing such disasters for the comparison operators. I.e. one weakness is not justification for opening the door to all weakness.
>
> Interestingly, by shutting the door on misuse of the comparison operators, it seems D has been successful in discouraging nutburger designs like overloading '+' to mean 'OR'.
>
>> The language you just provide a set of tools, then it's up the to the programmer
>> to do what he/she wants to do.
>
> That can be used to justify any feature at all.

This is not an argument to justify adding just any feature, it's an argument that it is idiocy to give a programmer a powerful tool, and then impose arbitrary limitations upon how they are allowed to use it.

One of the most popular topics of discussion in this forum is "Why is D not more widely adopted?" and "What can we do to get broader adoption for D?"

Perhaps one of the more obvious answers is: Do not prevent programmers from doing something solely on the basis that _you_ would not want to do it.

I think camelCase is hideous, but does that mean I should forbid another programmer defining symbols in that style? Of course not. That they are able to write their code that way doesn't mean I have to, and doesn't mean I have to use or interface with their code. I agree that '+' should always mean addition and '~' should always mean concatenation, but does that mean I should forbid another programmer from defining them differently? Of course not. Just because they are able to do it that way doesn't mean I have to, or that I have to use their code.

If I thought '>' and '<' should always mean arithmetic comparison, does that mean I should forbid another programmer from defining them differently?

You need to understand that _you are not the only one writing code in this language_. Your use cases do not summarize all possible use cases. That you do not need to use a tool in a specific way is not a valid argument against allowing others to use the tool that way.

Give us a rational argument. We are unconcerned with your personal dogma. What you refer to as a weakness I view as a strength. Programmers require more flexibility and expressiveness, not less.