UFCS and constructors

Jonathan M Davis jmdavisProg at gmx.com
Tue Jul 2 20:21:56 PDT 2013


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!

> > The closest that you could get would be a factory function, which is
> > quite different. But constructors themselves cannot be generic. As such,
> > using constructors with UFCS in generic code just doesn't work, meaning
> > that the only gain that you're getting from using UFCS with constructors
> > is that you get a slightly different syntax that you might like better
> > for one reason or another. But I see no technical reason why it could add
> > any benefit over simply calling the constructor normally. And as such, I
> > think that allowing UFCS to work with constructors is definitely an
> > anti-feature.
> > ...
> 
> To be an anti-feature it has to be harmful, not just of less benefit
> than some other (aspect of the) feature.

I _do_ think that it's harmful. It obfuscates code without adding any benefit.

- Jonathan M Davis


More information about the Digitalmars-d mailing list