April 09, 2013
On Mon, 08 Apr 2013 19:48:12 -0400, bearophile <bearophileHUGS@lycos.com> wrote:

> On request by Maxim Fomin I ask an opinion here. This is a very small enhancement request, that for me is borderline bug report (so originally I didn't plan in showing it in the main D newsgroup):
>
> http://d.puremagic.com/issues/show_bug.cgi?id=9857
>
>
>
> Maybe this should be valid:
>
>
> struct Foo {
>      int opCall(bool b) {
>          return 0;
>      }
> }
> void main() {
>     Foo foo;
>     auto b1 = foo(true); // OK
>     auto b2 = true.foo;  // Error
> }
>
>
> dmd 2.063alpha gives:
>
> temp.d(9): Error: no property 'foo' for type 'bool'

I agree, it should be valid.

A rewrite should be a rewrite, not some special-cased thing.

The rules are simple:

given a.b(...)

1. if a.b(...) compiles, then call it
2. otherwise if b(a, ...) compiles, call it.
3. otherwise, error.

-Steve
April 09, 2013
On Mon, 08 Apr 2013 23:49:14 -0400, kenji hara <k.hara.pg@gmail.com> wrote:

> UFCS should just work only for 'functions'.
> 'foo' is not a function, rather it is a functor. So this is proper behavior.

foo.opCall is a function.  When you invoke foo is synonymous with foo.opCall

The same should be true for delegates, function pointers, function templates, function aliases, alias this, etc.

-Steve
April 09, 2013
On 04/09/2013 04:10 PM, Maxim Fomin wrote:
> On Tuesday, 9 April 2013 at 09:03:55 UTC, Timon Gehr wrote:
>> This is getting old. We should discuss the general issue, issue 9857
>> is just another instance of it.
>>
>> Namely:
>>
>> If the language defines a rewrite from A to B and from B to C, is a
>> rewrite from A to C implied?
>
> If a + b is rewritten as a.opBinary according to operator overloading
> and a.opBinary as opBinary(a,..) is rewritten according to UFCS, it does
> not necessarily mean that this works together.
>

If it does not then it has to be specified that the first a.opBinary is a different construct from the second a.opBinary.

>> I'd say yes, because this is the obvious behaviour. If it is not
>> there, we have to add a magical "has already been rewritten" flag,
>> countering intuition. Furthermore, as far as I am concerned, this is
>> easier to implement. DMD's inconsistent behaviour has been discussed
>> on d.D.learn multiple times.
>
>  From what I know there is no code in dmd that intentionally disables
> the feature

I didn't claim it was intentional. In fact, I suspect it is an implementation bug since nothing except the implementation hints that it should not work.

> and it would be harder to implement the feature than to keep
> things as they stand (according to discussions on bugzilla).
>

I wouldn't know about the DMD code base.

>> Furthermore, the only argument brought up against this so far is that
>> some language constructs are special and ergo they must be mutually
>> incompatible. This is a complete non sequitur.
>>
>
> It seems that you ignore arguments (strictly speaking you are
> simplifying them).
>

I am abstracting their essence. If you think there was any argument that does not fit the above description, feel free to bring it up.

>>> Jonathan Davis doesn't like this. For more information I suggest to take
>>> a look at the thread in Bugzilla.
>>> ...
>>
>> There is not more information there, it's just given in a blown up
>> representation. He does not justify his opinion.
>
> That's not funny more. It is really interesting to hear from you saying
> that somebody does not provide bases for opinions because it is you who
> are known to post argument without justification ignoring everything
> previous
> (for ex.
> http://www.digitalmars.com/d/archives/digitalmars/D/Possible_UDA_bug_190800.html).
>

I am flattered you went through the hassle of searching the forums in order to build an irrelevant ad hominem argument.
Note however, that the thread quoted contains justification for every opinion I have posted.
On a general note, NG conversations are not linear and there may be race conditions.
April 10, 2013
On Tuesday, 9 April 2013 at 16:36:09 UTC, Andrei Alexandrescu wrote:
> On 4/9/13 12:27 PM, deadalnix wrote:
>> On Tuesday, 9 April 2013 at 16:22:08 UTC, Andrei Alexandrescu wrote:
>>> How do you address construction of immutable objects?
>>>
>>
>> In general, the first assignement of a field in a constructor must be
>> handled as a declaration, not as an assignement. It solve
>> const/immutable construction issues as well as avoiding unecessary
>> copy/destruction as Ali pointed in a recent post.
>>
>> The magic only happens in the constructor, so it can still be considered
>> as a regular function seen from the outside.
>
> Right. This part I agree with. All I'm saying is that constructors are typechecked differently from other functions, so they must be distinguished somehow. Probably we're in violent agreement, or if not: are you suggesting a change?
>

Constructor used to create lvalues, and so behave differently. I'm not sure what is the expected behavior at the end, but I think indeed that we envision the same thing here.

BTW, what do you mean by different typechecking rules ? How is it different than the code snippet posted above ?
April 10, 2013
On Tuesday, 9 April 2013 at 19:08:51 UTC, Timon Gehr wrote:
> I am abstracting their essence. If you think there was any argument that does not fit the above description, feel free to bring it up.

a) UFCS and overloading are distinct topics. One does not enforce other to work in a particular way. For example, UFCS does not mean that a.typeid should be rewritten as typeid(a) or foo!int can be written as int.foo. Judging by enhancement requests in bugzilla, there is trend for asking anything like 'a..b..c'  to be writable as 'a.b...c' in general. None of such ideas is 100% right per se, including operator overloading.

b) UFCSing operator overloading is a feature which can be easily and likely to broken. By easily broken I mean that despite the idea looks 'cool', its advantages evaporate when there are multiple opBinaries and other stuff. It is possible to rewrite conflicting function name to other and use it, but it isn't possible to rewrite conflicting basic expression in terms of other basic expressions. There is no possibility for S[my.bar.mod.opCall](). The idea blows up and you have to use function call as currently. By likely to be broken I mean higher probability to run in name conflict with operators than with regular methods (and it would happen very likely because idea seems to be popular).

By the way, not all operators can be overloaded because "... These operators [comma, ternary, && and || ] were considered to create more confusion than flexibility if ever overloaded..." which does not necessarily means that this decision is "incomplete" and "non sequitur".

>>>> Jonathan Davis doesn't like this. For more information I suggest to take
>>>> a look at the thread in Bugzilla.
>>>> ...
>>>
>>> There is not more information there, it's just given in a blown up
>>> representation. He does not justify his opinion.
>>
>> That's not funny more. It is really interesting to hear from you saying
>> that somebody does not provide bases for opinions because it is you who
>> are known to post argument without justification ignoring everything
>> previous
>> (for ex.
>> http://www.digitalmars.com/d/archives/digitalmars/D/Possible_UDA_bug_190800.html).
>>
>
> I am flattered you went through the hassle of searching the forums in order to build an irrelevant ad hominem argument.
> Note however, that the thread quoted contains justification for every opinion I have posted.
> On a general note, NG conversations are not linear and there may be race conditions.

I don't care of flattering you, but I do not like when arguments are distorted or described as being absent, or people are portrayed as having no idea what they are talking about.

Surely, I do understand advantages of the idea and understand why the idea is considered to be logical, I object not because being programming sadist, but because consider idea harmful and easy to abuse.
April 10, 2013
On 04/10/2013 02:59 PM, Maxim Fomin wrote:
> On Tuesday, 9 April 2013 at 19:08:51 UTC, Timon Gehr wrote:
>> I am abstracting their essence. If you think there was any argument
>> that does not fit the above description, feel free to bring it up.
>
> a) UFCS and overloading are distinct topics. One does not enforce other
> to work in a particular way.

But this would support my view on the matter. I think this point has not been brought up in support of your view so far.

> For example, UFCS does not mean that
> a.typeid should be rewritten as typeid(a)

This is 100% a parser feature, there is no overloading involved.

> or foo!int can be written as int.foo.

No call syntax involved.

> Judging by enhancement requests in bugzilla, there is trend for
> asking anything like 'a..b..c'  to be writable as 'a.b...c' in general.
> None of such ideas is 100% right per se, including operator overloading.
>

This is not precise enough for me to get anything out of it.

> b) UFCSing operator overloading is a feature which can be easily and
> likely to broken. By easily broken I mean that despite the idea looks
> 'cool', its advantages evaporate when there are multiple opBinaries and
> other stuff.

This is an argument which is similar to the general scheme I have sketched. The above is a somewhat elaborate claim that operator overloading is special

> It is possible to rewrite conflicting function name to
> other and use it, but it isn't possible to rewrite conflicting basic
> expression in terms of other basic expressions.

And it is not necessary. Why would it be?

> There is no possibility for S[my.bar.mod.opCall]().

I don't get that.

> The idea blows up and you have to use function call as currently.

You have to use function calls in any case, because overloaded operators are just function templates. Whether your operation is called "+" of "f" is a mere naming issue.

> By likely to be broken I mean higher
> probability to run in name conflict with operators than with regular
> methods

Name conflicts can be resolved in the usual fashion. Name conflicts occur only if both functions accept the same kind of input. There are not many ways to meaningfully overload operators for the same kind of data type. Furthermore, the same function name is not meaningful for every function. The "more likely" rests on the assumption that infix operator names are appropriate names for more functions than other function names. This is not justified.

> (and it would happen very likely because idea seems to be popular).
>

This therefore assumes that "many" will furiously start to name their functions in _inappropriate_ ways.
You have yet to provide a likely scenario.

> By the way, not all operators can be overloaded because "... These
> operators [comma, ternary, && and || ] were considered to create more
> confusion than flexibility if ever overloaded..."

I'd like to keep the discussion focused. We are discussing the general behaviour of rewriting, not specific rewrites. There is no question that D's treatment of non-alphanumeric function symbols is not the best possible.

> which does not necessarily means that this decision  is "incomplete" and "non sequitur".
>

This sentence does not make any sense.

> ...
>
> [...] I do not like when arguments are
> distorted or described as being absent, or people are portrayed as
> having no idea what they are talking about.
>

Me neither.

> Surely, I do understand advantages of the idea and understand why the
> idea is considered to be logical,

Do you also understand why special rules that restrict orthogonality of language features are harmful?

> I object not because being programming
> sadist, but because consider idea harmful and easy to abuse.

Most D features are easy to abuse. Deciding whether a feature is used in an abusive way is subjective at best and not generally decidable by an algorithm in any case.
April 10, 2013
On 2013-04-10, 14:59, Maxim Fomin wrote:

> a) UFCS and overloading are distinct topics. One does not enforce other to work in a particular way.

Exactly. So if a + b may be rewritten a.opBinary(b), and a.foo(b) may be
rewritten foo(a, b), it makes sense that a + b may be rewritten
opBinary(a, b). Otherwise, UFCS forces operator overloading to work in a
particular way (an/or the other way around).


> For example, UFCS does not mean that a.typeid should be rewritten as typeid(a) or foo!int can be written as int.foo.

The reason UFCS does not work for the first is special casing in the
parser.

The reason it does not work for the second is it's not a function call
at all (or, possibly, a parameter-less one).


> b) UFCSing operator overloading is a feature which can be easily and likely to broken. By easily broken I mean that despite the idea looks 'cool', its advantages evaporate when there are multiple opBinaries and other stuff.
[snip]
> (and it would happen very likely because idea seems to be popular).

That a feature is popular is rarely a good argument for removing it.
The exact same argument has been used against operator overloading in
the past, and apart from C++'s streams, I've never heard of anyone
who's actually abused the feature, only these hypothetical scenarios
where someone overload + to mean 'connect to database/launch missiles'.
It's not a good argument. People will not start searching for ways to
abuse a feature just because it's there, and accidental problems are
likely to be rare and easily circumvented.

Would you believe the exact same argument was used against regular
function overloading back in the day?


> There is no possibility for S[my.bar.mod.opCall]().

I have no idea what you're even trying to communicate, much less prove,
with this construct. Complexity is complex? People will write ugly code
no matter? I guess the first part is a static opIndex, and it basically
behaves like an AA with function keys and values? What are you even
trying to do?


> By the way, not all operators can be overloaded because "... These operators [comma, ternary, && and || ] were considered to create more confusion than flexibility if ever overloaded..." which does not necessarily means that this decision is "incomplete" and "non sequitur".

Of course not. Fairly reasonable arguments are even presented right there.
I am still somewhat more in favor of letting the programmer have that
flexibility, and berate and/or fire him/her if it ever gets used.

I have occasionally wanted to overload && and ||, though in those cases
| and & have been good enough. I'd love to have a few more operators,
though. × comes immediately to mind, and ⋅, ∩, ∪, ⊂, and ⊃ quickly
follow.

-- 
Simen
April 10, 2013
On 04/09/2013 09:27 AM, deadalnix wrote:

> In general, the first assignement of a field in a constructor must be
> handled as a declaration, not as an assignement. It solve
> const/immutable construction issues as well as avoiding unecessary
> copy/destruction as Ali pointed in a recent post.

The following thread:

  http://forum.dlang.org/thread/khu6tl$q8o$1@digitalmars.com

It contains a link to the following enhancement request:

  http://d.puremagic.com/issues/show_bug.cgi?id=9732

Ali

1 2 3
Next ›   Last »