View mode: basic / threaded / horizontal-split · Log in · Help
August 30, 2007
Re: class extensions
Lars Ivar Igesund wrote:
> [...]
> It will also be directly detrimental to maintainability when used for user
> defined types, as you no longer will be able to decide where a function is
> implemented by only looking at the call site (given inheritance and
> polymorphism this can in cases be difficult enough, but at least you have a
> type hierarchy to look to).

Well, usually a simple change to the import list will reveal where each 
functions are defined. I wouldn't see that as an argument against this 
feature.

Apart from that, in an ideal world, the code is well documented enough 
to not have to determine the location of a function/method 
implementation yourself, anyways. Of course, this is the *ideal*, but 
maybe this encourages some to document better.
August 30, 2007
Re: class extensions
Alexander Panek wrote:

> Lars Ivar Igesund wrote:
>> [...]
>> It will also be directly detrimental to maintainability when used for
>> user defined types, as you no longer will be able to decide where a
>> function is implemented by only looking at the call site (given
>> inheritance and polymorphism this can in cases be difficult enough, but
>> at least you have a type hierarchy to look to).
> 
> Well, usually a simple change to the import list will reveal where each
> functions are defined. I wouldn't see that as an argument against this
> feature.

I probably miss your point here, but it certainly shouldn't be necessary to
change your code to find out what it does?

> 
> Apart from that, in an ideal world, the code is well documented enough
> to not have to determine the location of a function/method
> implementation yourself, anyways. Of course, this is the *ideal*, but
> maybe this encourages some to document better.

One should of course always document, but as many of the other suggestions
in the Future of D presentation leans towards self documenting code (pure
and nothrow functions for instance), I see this change as quite the
opposite in that regard.

-- 
Lars Ivar Igesund
blog at http://larsivi.net
DSource, #d.tango & #D: larsivi
Dancing the Tango
August 30, 2007
Re: class extensions
Alexander Panek wrote:
> Lars Ivar Igesund wrote:
>> [...]
>> It will also be directly detrimental to maintainability when used for 
>> user
>> defined types, as you no longer will be able to decide where a 
>> function is
>> implemented by only looking at the call site (given inheritance and
>> polymorphism this can in cases be difficult enough, but at least you 
>> have a
>> type hierarchy to look to).
> 
> Well, usually a simple change to the import list will reveal where each 
> functions are defined. I wouldn't see that as an argument against this 
> feature.
> 
> Apart from that, in an ideal world, the code is well documented enough 
> to not have to determine the location of a function/method 
> implementation yourself, anyways. Of course, this is the *ideal*, but 
> maybe this encourages some to document better.

On the other hand, the ambiguity problem:

class A {
    int foo (int);
}

int foo (A, int);

..leads or at least may lead to maintenance problems, anyways.

(Yes, I might have missed the point in the other post :P)
August 30, 2007
Re: class extensions
kris wrote:
...
> 
> And it potentially introduces additional namespace issues, hijacking 
> issues, and compilation errors for large and/or long-term software 
> development projects. The commercial-development space is where D ought 
> to target, if it's to rise well above being just another enthusiasts 
> playground :p

I agree, although I am that enthusiast. The main reason I liked this 
feature is 1) see Jarret's post and 2) I find it is easier to write 
small classes and extend them with free functions, good class design is 
hard. But if there are such issues then it is probably not worth it.

> A conservative approach would remove the existing idiom with arrays, 
> rather than propagate it, and address concerns instead by perhaps 
> looking at alternate approaches for supporting 'properties' (C# for 
> example). Are you thinking this makes a good solution for 'properties' 
> in general? As has been discussed recently?

No, not for properties. I never think of the current way properties are 
handled really as 'properties' in the sense of data members. They are 
just an alternative syntax for functions with 0 or 1 arguments in my 
book, with perhaps a hint to their role in a design.
Now this is my opinion, maybe misinformed, but I don't think class 
properties are important. They are just dressed up getters/setters, 
which is not so good an idiom to use frequently.

> Just because some folks apparently like it, and are vocal about it, 
> doesn't necessarily make it "generally appreciated"? That's a problem 
> with newsgroups and forums though ... it's perhaps easy to get a skewed 
> perspective?

Sure, although I have never seen one single post that objects to array 
properties, nor have I encountered bugs / problems related to it.

> As for extending to other types, that's cool! I just feel this 
> particular idiom potentially builds smoldering fires larger than the 
> one(s) it is attempting to extinguish (or perhaps it's not even trying 
> to resolve anything?). If that is the case it is hardly an adequate 
> resolution, and will simply return to bite D in the buttocks.

My impression was that it is mainly for syntactic sugar, and maybe there 
was a notion of how it could be used in generic programming? Can't think 
of an issue that it solves.

> As such, I suspect alternatives should be given great consideration (or 
> /greater/ consideration) and the relative trade-offs should be weighed 
> appropriately. Yourself, and others, may feel that's not necessary or 
> has been adequately performed already? I don't feel that way, and it's 
> not the impression I got from the conference :-D

No I don't pretend to have thought through the issues, I don't think I 
can. That's why I asked you!
August 30, 2007
Re: class extensions
Alexander Panek wrote:
> Bill Baxter wrote:
>> [...]
>> But Walter seems to think it's ok the way it is.  Given that, I can 
>> definitely see how he'd think making a.foo uniformly interchangable 
>> with foo(a) makes sense.  I guess with property syntax and this 
>> combined we'll have
>>    "a.value" == "value(a)" == "value = a"
> 
> Oooh it looks like this would be possible to write:
> 
> 3.times = (int a) { Stdout(a.toUtf8).newline; }
> 
> ...fun! :D

I reiterate what I've said about three times now: I watch as D slowly turns into Ruby.  :)

(Although I actually like pseudo-members.  ColdC has this as well, but by modifying a 
type-lib object; $String.foo() callable as "abc".foo() for example.)

-- Chris Nicholson-Sauls
August 30, 2007
Re: class extensions
Chris Nicholson-Sauls wrote:
> I reiterate what I've said about three times now: I watch as D slowly 
> turns into Ruby.  :)
Hehe. They indeed have similarities - maybe not in language theory or 
overall concept, but in innovation. Having (part of) Ruby's 
expressiveness in D would be a very neat thing, as long as it doesn't 
affect other concepts and goals of D.

> (Although I actually like pseudo-members.  ColdC has this as well, but 
> by modifying a type-lib object; $String.foo() callable as "abc".foo() 
> for example.)

That's actually possible already in D (D1, even):

//
import tango.io.Stdout;

void print (char[] s) {
    Stdout(s);
}

void main () {
    "Hello world!".print(); // omitting () is not possible, though
}
//
August 30, 2007
Re: class extensions
kris wrote:
> Lutger wrote:
>> kris wrote:

> And it potentially introduces additional namespace issues, hijacking 
> issues, and compilation errors for large and/or long-term software 
> development projects. The commercial-development space is where D ought 
> to target, if it's to rise well above being just another enthusiasts 
> playground :p

Namespace issues are why I don't currently find much use for the array 
trick.  If you put your array trick functions in a module, they're 
mostly going to have short names like "find" and "index".  So if you 
import that module normally it will clobber a valuable chunk of your 
namespace with little words like that.  But doing a static or renamed 
import causes the things not to work.  "arrayfn.find" can't be used as a 
property.  Ok so you can static import and then alias just the ones you 
want to use in the current module, possibly down at function scope to 
limit the namespace clashing.  But that's kind of a pain.

The error messages are also not very intuitive currently.  You type 
foo.bar(x,y) and get the error message "bar does not match types (int, 
int, int)"    Wait -- I'm not even calling bar with three args!?  Oh yeh 
that member syntax thing.  And if there really *is* a member with that 
name in the current context then it will shadow the external one even 
though it *looks* like foo.bar should be unambiguously scoped by foo.

These are from recent experience trying to emulate C++ iterators on top 
of D arrays.  For instance I wanted to be able to say  darray.begin() to 
get an iterator to an array.  Forget it.  Most classes in which I want 
to use that trick already have their own 'begin()' member which shadows 
the external begin(T)(T[]) function.

So my feeling is that for this to be more useful:
1) Extension members should be marked as such and *only* be allowed to 
be called with member syntax.  Those not marked as such will not be 
allowed to be called with member syntax.  (if you need both then it's 
easy enough to write a trivial forwarding function.)

2) Inside a class/struct scope, lookup of foo.bar should ignore methods 
of the local class.  (this would be a natural side effect of #1 though. 
 it already means extension members would do lookup differently than 
normal function lookup)

--bb
August 30, 2007
Re: class extensions
On Fri, 31 Aug 2007, Bill Baxter wrote:

> Namespace issues are why I don't currently find much use for the array trick.
> If you put your array trick functions in a module, they're mostly going to
> have short names like "find" and "index".  So if you import that module
> normally it will clobber a valuable chunk of your namespace with little words
> like that.  But doing a static or renamed import causes the things not to
> work.  "arrayfn.find" can't be used as a property.  Ok so you can static
> import and then alias just the ones you want to use in the current module,
> possibly down at function scope to limit the namespace clashing.  But that's
> kind of a pain.
> 
> The error messages are also not very intuitive currently.  You type
> foo.bar(x,y) and get the error message "bar does not match types (int, int,
> int)"    Wait -- I'm not even calling bar with three args!?  Oh yeh that
> member syntax thing.  And if there really *is* a member with that name in the
> current context then it will shadow the external one even though it *looks*
> like foo.bar should be unambiguously scoped by foo.
> 
> These are from recent experience trying to emulate C++ iterators on top of D
> arrays.  For instance I wanted to be able to say  darray.begin() to get an
> iterator to an array.  Forget it.  Most classes in which I want to use that
> trick already have their own 'begin()' member which shadows the external
> begin(T)(T[]) function.
> 
> So my feeling is that for this to be more useful:
> 1) Extension members should be marked as such and *only* be allowed to be
> called with member syntax.  Those not marked as such will not be allowed to be
> called with member syntax.  (if you need both then it's easy enough to write a
> trivial forwarding function.)
> 
> 2) Inside a class/struct scope, lookup of foo.bar should ignore methods of the
> local class.  (this would be a natural side effect of #1 though.  it already
> means extension members would do lookup differently than normal function
> lookup)
> 
> --bb

Don't overlook the changes upcoming in 2.0 to the overload resolution 
logic.  They'll greatly reduce (if not eliminate) the problem.  Many of 
the changes in 2.0 in isolation might introduce problems, but together 
make for a more powerful whole.

Later,
Brad
August 30, 2007
Re: class extensions
Bill Baxter wrote:
> kris wrote:
>> Lutger wrote:
>>> kris wrote:
> 
>> And it potentially introduces additional namespace issues, hijacking 
>> issues, and compilation errors for large and/or long-term software 
>> development projects. The commercial-development space is where D 
>> ought to target, if it's to rise well above being just another 
>> enthusiasts playground :p
> 
> Namespace issues are why I don't currently find much use for the array 
> trick.  If you put your array trick functions in a module, they're 
> mostly going to have short names like "find" and "index".  So if you 
> import that module normally it will clobber a valuable chunk of your 
> namespace with little words like that.  But doing a static or renamed 
> import causes the things not to work.  "arrayfn.find" can't be used as a 
> property.  Ok so you can static import and then alias just the ones you 
> want to use in the current module, possibly down at function scope to 
> limit the namespace clashing.  But that's kind of a pain.
> 
> The error messages are also not very intuitive currently.  You type 
> foo.bar(x,y) and get the error message "bar does not match types (int, 
> int, int)"    Wait -- I'm not even calling bar with three args!?  Oh yeh 
> that member syntax thing.  And if there really *is* a member with that 
> name in the current context then it will shadow the external one even 
> though it *looks* like foo.bar should be unambiguously scoped by foo.
> 
> These are from recent experience trying to emulate C++ iterators on top 
> of D arrays.  For instance I wanted to be able to say  darray.begin() to 
> get an iterator to an array.  Forget it.  Most classes in which I want 
> to use that trick already have their own 'begin()' member which shadows 
> the external begin(T)(T[]) function.
> 
> So my feeling is that for this to be more useful:
> 1) Extension members should be marked as such and *only* be allowed to 
> be called with member syntax.  Those not marked as such will not be 
> allowed to be called with member syntax.  (if you need both then it's 
> easy enough to write a trivial forwarding function.)
> 
> 2) Inside a class/struct scope, lookup of foo.bar should ignore methods 
> of the local class.  (this would be a natural side effect of #1 though. 
>  it already means extension members would do lookup differently than 
> normal function lookup)
> 
> --bb


Amen
August 30, 2007
Re: class extensions
Bill Baxter wrote:
> kris wrote:
>> Lutger wrote:
>>> kris wrote:
> 
>> And it potentially introduces additional namespace issues, hijacking 
>> issues, and compilation errors for large and/or long-term software 
>> development projects. The commercial-development space is where D 
>> ought to target, if it's to rise well above being just another 
>> enthusiasts playground :p
> 
> Namespace issues are why I don't currently find much use for the array 
> trick.  If you put your array trick functions in a module, they're 
> mostly going to have short names like "find" and "index".  So if you 
> import that module normally it will clobber a valuable chunk of your 
> namespace with little words like that.  But doing a static or renamed 
> import causes the things not to work.  "arrayfn.find" can't be used as a 
> property.  Ok so you can static import and then alias just the ones you 
> want to use in the current module, possibly down at function scope to 
> limit the namespace clashing.  But that's kind of a pain.

Or just use selective import to do the same thing:

import cashew .utils .Array : contains, push, pop ;

> The error messages are also not very intuitive currently.  You type 
> foo.bar(x,y) and get the error message "bar does not match types (int, 
> int, int)"    Wait -- I'm not even calling bar with three args!?  Oh yeh 
> that member syntax thing.  And if there really *is* a member with that 
> name in the current context then it will shadow the external one even 
> though it *looks* like foo.bar should be unambiguously scoped by foo.

I agree; but I consider it a lookup bug, not an inherent aspect of pseudo-members.

> These are from recent experience trying to emulate C++ iterators on top 
> of D arrays.  For instance I wanted to be able to say  darray.begin() to 
> get an iterator to an array.  Forget it.  Most classes in which I want 
> to use that trick already have their own 'begin()' member which shadows 
> the external begin(T)(T[]) function.

static import FooBar foo.bar : begin ;
alias FooBar.begin fb_begin ;

//...
darray.fb_begin()



Yeah, okay, that is a bit borked.

> So my feeling is that for this to be more useful:
> 1) Extension members should be marked as such and *only* be allowed to 
> be called with member syntax.  Those not marked as such will not be 
> allowed to be called with member syntax.  (if you need both then it's 
> easy enough to write a trivial forwarding function.)

Its not a bad idea.  The "trivial forwarding function" should be inlineable anyhow.  Maybe 
a "context" parameter?  Something like:
size_t indexOf : T[] array (T) (T elem) { ... }

Where the (':' param) after the function name creates the context-param.  Other examples:

ulong area : IShape shp () { ... }

void unique : inout T[] array (T) () { ... }


Its just a random on-the-spot idea.

> 2) Inside a class/struct scope, lookup of foo.bar should ignore methods 
> of the local class.  (this would be a natural side effect of #1 though. 
>  it already means extension members would do lookup differently than 
> normal function lookup)

Aye.

-- Chris Nicholson-Sauls
1 2 3
Top | Discussion index | About this forum | D home