April 09, 2013
deadalnix:

> I don't think this makes any sense. Constructor are not regular function.

From studying functional languages like Haskell I have learnt that considering "constructors" like the other functions gives some advantages. The uniformity of the idea of "function" is very useful.

What you are saying here has no content, so it has no value (it's equivalent to a -0 vote). If you want to put an argument you have to explain what are the practical disadvantages/risks in D of calling a struct opCall with the UFCS.

Bye,
bearophile
April 09, 2013
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.

> 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 and it would be harder to implement the feature than to keep things as they stand (according to discussions on bugzilla).

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

>> 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).
April 09, 2013
On Tuesday, 9 April 2013 at 13:02:27 UTC, bearophile wrote:
> deadalnix:
>
>> I don't think this makes any sense. Constructor are not regular function.
>
> From studying functional languages like Haskell I have learnt that considering "constructors" like the other functions gives some advantages. The uniformity of the idea of "function" is very useful.
>

Right now, in D, you'll find plenty of magic associated with constructors. This is fundamentaly problematic when you want to disguise them as functions.

I would be in general for reducing the magic associated with constructor in order to allow them to behave like function, but right now, they are different beasts.

> What you are saying here has no content, so it has no value (it's equivalent to a -0 vote). If you want to put an argument you have to explain what are the practical disadvantages/risks in D of calling a struct opCall with the UFCS.
>

UFCS work with function, but do not with first class functions (ie values) or delegate. opCall on struct is much closer to a delegate than a function.
April 09, 2013
On 4/9/13 10:35 AM, deadalnix wrote:
> On Tuesday, 9 April 2013 at 13:02:27 UTC, bearophile wrote:
>> deadalnix:
>>
>>> I don't think this makes any sense. Constructor are not regular
>>> function.
>>
>> From studying functional languages like Haskell I have learnt that
>> considering "constructors" like the other functions gives some
>> advantages. The uniformity of the idea of "function" is very useful.
>>
>
> Right now, in D, you'll find plenty of magic associated with
> constructors. This is fundamentaly problematic when you want to disguise
> them as functions.
>
> I would be in general for reducing the magic associated with constructor
> in order to allow them to behave like function, but right now, they are
> different beasts.

They are different than regular functions by necessity. A constructor must start on an raw object ("unprepared" in a sense) and bring it to a meaningful state. In the case of immutable and const objects, that grants the constructor special characteristics that are very unlike regular functions. So they are special.

Andrei

April 09, 2013
On Tuesday, 9 April 2013 at 15:29:42 UTC, Andrei Alexandrescu wrote:
> They are different than regular functions by necessity. A constructor must start on an raw object ("unprepared" in a sense) and bring it to a meaningful state. In the case of immutable and const objects, that grants the constructor special characteristics that are very unlike regular functions. So they are special.
>

They need magic inside, it doesn't need to leak outside.

As now they are rvalues, this is easy to type the constructor as follow :

struct S {
    T t;

    this(T t) {
        this.t = t;
    }

    // Becomes.
    static S __ctor(T t) {
        S this = S.init; // Magic !!
        this.t = t;
        return this;  // Magic !!
    }
}

The magic don't need to leak outside.
April 09, 2013
On 4/9/13 11:43 AM, deadalnix wrote:
> On Tuesday, 9 April 2013 at 15:29:42 UTC, Andrei Alexandrescu wrote:
>> They are different than regular functions by necessity. A constructor
>> must start on an raw object ("unprepared" in a sense) and bring it to
>> a meaningful state. In the case of immutable and const objects, that
>> grants the constructor special characteristics that are very unlike
>> regular functions. So they are special.
>>
>
> They need magic inside, it doesn't need to leak outside.

Agreed.

> As now they are rvalues, this is easy to type the constructor as follow :
>
> struct S {
> T t;
>
> this(T t) {
> this.t = t;
> }
>
> // Becomes.
> static S __ctor(T t) {
> S this = S.init; // Magic !!
> this.t = t;
> return this; // Magic !!
> }
> }
>
> The magic don't need to leak outside.

I'm lost.

Andrei
April 09, 2013
On Tuesday, 9 April 2013 at 15:56:10 UTC, Andrei Alexandrescu wrote:
> On 4/9/13 11:43 AM, deadalnix wrote:
>> On Tuesday, 9 April 2013 at 15:29:42 UTC, Andrei Alexandrescu wrote:
>>> They are different than regular functions by necessity. A constructor
>>> must start on an raw object ("unprepared" in a sense) and bring it to
>>> a meaningful state. In the case of immutable and const objects, that
>>> grants the constructor special characteristics that are very unlike
>>> regular functions. So they are special.
>>>
>>
>> They need magic inside, it doesn't need to leak outside.
>
> Agreed.
>
>> As now they are rvalues, this is easy to type the constructor as follow :
>>
>> struct S {
>> T t;
>>
>> this(T t) {
>> this.t = t;
>> }
>>
>> // Becomes.
>> static S __ctor(T t) {
>> S this = S.init; // Magic !!
>> this.t = t;
>> return this; // Magic !!
>> }
>> }
>>
>> The magic don't need to leak outside.
>
> I'm lost.
>
> Andrei

What I'm saying is that no magic need to be done outside the constructor, and it can be considered as a regular function.

For instance, in the code snippet above, the constructor can be translated into the __ctor function (in D like) by adding the magic.

This would allow to merge constructors and functions, and handle both the same way.
April 09, 2013
On 4/9/13 12:16 PM, deadalnix wrote:
> On Tuesday, 9 April 2013 at 15:56:10 UTC, Andrei Alexandrescu wrote:
>> On 4/9/13 11:43 AM, deadalnix wrote:
>>> On Tuesday, 9 April 2013 at 15:29:42 UTC, Andrei Alexandrescu wrote:
>>>> They are different than regular functions by necessity. A constructor
>>>> must start on an raw object ("unprepared" in a sense) and bring it to
>>>> a meaningful state. In the case of immutable and const objects, that
>>>> grants the constructor special characteristics that are very unlike
>>>> regular functions. So they are special.
>>>>
>>>
>>> They need magic inside, it doesn't need to leak outside.
>>
>> Agreed.
>>
>>> As now they are rvalues, this is easy to type the constructor as
>>> follow :
>>>
>>> struct S {
>>> T t;
>>>
>>> this(T t) {
>>> this.t = t;
>>> }
>>>
>>> // Becomes.
>>> static S __ctor(T t) {
>>> S this = S.init; // Magic !!
>>> this.t = t;
>>> return this; // Magic !!
>>> }
>>> }
>>>
>>> The magic don't need to leak outside.
>>
>> I'm lost.
>>
>> Andrei
>
> What I'm saying is that no magic need to be done outside the
> constructor, and it can be considered as a regular function.
>
> For instance, in the code snippet above, the constructor can be
> translated into the __ctor function (in D like) by adding the magic.
>
> This would allow to merge constructors and functions, and handle both
> the same way.

How do you address construction of immutable objects?

Andrei
April 09, 2013
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.
April 09, 2013
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?

Andrei