On 03/04/2011 09:31 AM, Kevin Bealer wrote:
== Quote from Jonathan M Davis ([email protected])'s article
But that's not how the function is written. The left parameter is the
destination. If myString.strcpy(myString2) is confusing, I would expect
strcpy(myString, myString2) to be just as confusing. I don't see how using the
member function call syntax like that makes it any more confusing. Not to
mention, functions with a source and destination like that end up in both orders
all the time, so I don't think that you can generally expect it in one order or
the other anyway.
- Jonathan M Davis

I personally think strcpy got it wrong anyway -- everyone says 'input and 
output',
not 'output and input', so it's weird to think of the output mentioned first.

Yes, I really agree, but (unfortunately?) we write
        target = source;

It's as if you wrote:

// everyone who uses this will get the argument order wrong at least once
int everythingNice(int spice, int sugar);

But that's a side note...

Personally, I think the UFCS for anything but arrays is an engraved invitation 
to
function hijacking.  Imagine defining this in your code:

int find(T, U)(T a, U b)
{
     ...
}

class Foo {
     int find(double x, char[] y);
};

Foo x;
x.find(a, "hello"); // would this call the template or the method?

Whoops -- now every class, structure, and array in your program has a method
called find() that hijacks any arguments that don't exactly match an existing
function.  If you call x.find(), you can't know if you are getting the method in
the class or a free function that got sucked in because of this syntax.  Of 
course
if you get the signature exactly right it probably prefers the method over the
free function.  Arrays are special because the only methods they have are *built
in* methods.  Thus, a basic understanding of the language makes it possible to
avoid the ambiguity.  But implementing UFCS for other types is a problem.

If I do "a.getIndex(5)" and the compiler says there is no method getIndex on 
class
A, this is a gift --- it is almost always the case that this is an error.  I 
doubt
I ever want getIndex(A, int) but wrote A.getIndex(5) or where I wanted f(A, int)
but wrote a.f(5).

If you want another method in your class *add it to your class*.  The reason it
makes sense to have it for arrays is so that you can define common methods 
across
all your types like "serialize" method or "toString" or "deepCopy" and know what
these methods do.  Then you can use them in templates.  Arrays can't be 
subclassed
to add the methods so you need a way to produce the same syntax as a method 
call.

Since arrays can't be derived from, UFCS fills in a real gap and doesn't mask
existing or future methods unless the interface for arrays changes which is 
rare,
we hope.  Allowing it for other types doesn't fill a gap, it creates an
overlap/ambiguity.  It doesn't let you do anything you can't already do.  It's
like a built-in alias this that you can't turn off and that matches across all 
the
free functions of the world if I'm understanding the matching correctly.

In most cases you can also use functions (for deepCopy etc) to work with both
classes and arrays, but this doesn't work with virtual functions, so the method
syntax is nicer for that.  So UFCS is justified to make arrays 'look like 
classes'
to template code.  But it's not justified in my opinion to make classes look 
like
classes with one more method.

I was a supporter of UFCS, but my opinion starts to change.
The main point for me was to allow client code enhance structs/classes according to specific needs. Eg you import a stream class and add it a 'serialize' pseudo-method. But now I start to think
1. libraries should be designed in such that this need is rare enough
2. one can and should subtype, thus making clear it's a new version

Unfortunately, this is not possible for structs (the 'alias this' hack is not subtyping (*), it's plain delegation instead). The absence of struct subtyping is a big drawback. Why is it so? (**)

Denis

(*) There is no common supertype, so one cannot have a func or collection accept both the original type and one or more customized types. And indeed there is no method dispatch. (**) Some OO languages have struct-like types (stack-allocated, value-semantics) *with* subtyping. See eg Oberon for a wonderful example.
--
_________________
vita es estrany
spir.wikidot.com

Reply via email to