class extensions

Chris Nicholson-Sauls ibisbasenji at gmail.com
Thu Aug 30 13:46:04 PDT 2007


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



More information about the Digitalmars-d mailing list