On Wednesday, 3 July 2013 at 03:22:16 UTC, Jonathan M Davis wrote:
On Wednesday, July 03, 2013 04:54:41 Timon Gehr wrote:
On 07/03/2013 04:12 AM, Jonathan M Davis wrote:
> On Wednesday, July 03, 2013 04:00:45 bearophile wrote:
>> deadalnix:
>>> The whole point of UFCS is to be able to provide additional
>>> custom "methods" to a object (class or struct). Constructor
>>> UFCS don't fulfill that use case.
>>> >>> Nothing is removed from the language as factories method >>> can be
>>> introduced anyway.
>> >> This frames the topic in a wrong way. Constructors are not >> normal >> functions, they are special, but functional languages show >> us
>> that's it's a very good idea to see them as functions.
>> >> And the original point of UFCS doesn't matter much. What >> matters >> is what are the practical disadvantages of allowing >> UFCSyntax for >> constructors (like the original post in this thread), and >> what >> are their practical advantages/uses (like a handy usage in >> UFCS >> chains). Then we take a look at what's the resulting >> balance and
>> we decide. And such decisions should then become the written
>> specifics of this part of the D design.
> > The primary benefit of UFCS is generic code, because if uses > UFCS, > generic code doesn't have to care whether a function is a > member function > or a free function (particularly when that can vary > drastically depending
> on what type is used to instantiate the template).

No. Generic code has to be careful with UFCS, because every method that is called on a suitable variable via UFCS can be (accidentally) replaced
by the client code.

That's the whole point! If you absolutely have to be certain that it's not calling a free function, then don't use UFCS, but the primary benefits of UFCS   are making it so that generic code doesn't have to care whether a function is a free function and making it so that types can overload the behavior of free functions (e.g. having a member function find which is optimized for that type
and can be used in place of std.algorithm.find).

> Construction is not and cannot be generic.

The point is that struct constructors can be generically used like other
callables.

import std.stdio, std.algorithm;

struct S{
int x;
}

void main(){
auto x = [1,2,3];
writeln(x.map!S);
}

There is nothing to be gained from subtly breaking this analogy. UFCS
can be applied to any callable.

You are probably not going to like this, but the following code also works:

import std.stdio;

struct S{
int opCall(int x){ return x+1; }
}

S s;

void main(){
auto x = 1;
writeln(x.s);
}

That is _very_ broken IMHO. It makes no sense for parens to be optional with
opCall. The whole point of opCall is to overload the parens!

- Jonathan M Davis

In a UFCS chain, it would make sense for the so-called "function object":

struct Incrementor
{
    int n;
    ref int opCall(ref int i)
    {
        return i+=n;
    }
}

int i, j;
auto incrementByTwo   = Incremementor(2);
auto incrementByThree = Incremementor(3);
i.incrementByTwo;
j.incrementByThree;

Here, the "function object" is treated just like a function (it is *designed* to behave like a function), so it should benefit from the same optional parens as a normal function.

However, yeah, I think a standalone arg-less opCall with no parens is stupid (unless someone has a usecase for it?): It's an alias this in disguise, nothing more.

Reply via email to