View mode: basic / threaded / horizontal-split · Log in · Help
August 30, 2007
Re: class extensions
Alexander Panek wrote:
> 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.

I'm sure we'll never, ever, see something quite like:
$db.commit @transaction unless @transaction.flag_set? :Simulate

But other than that... ;)

>> (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
> }
> //

Oh yes, I know.  :)  (See Cashew.)  But unlike D/1.x, ColdC supports this for all types 
(in its own weird way).  Right now it only works for arrays, and was originally just a 
fluke side-effect that got popular.

It looks like D/2.x is going to open up that Pandora's Box though.  Here's hoping it goes 
a lot better than the referenced myth.

-- Chris Nicholson-Sauls
August 30, 2007
Re: class extensions
Brad Roberts wrote:
> 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.

Yeh, that should help some.  But that doesn't seem to do anything about 
foo.bar() inside a class being treated as this.bar(foo).  I think that 
just shouldn't happen ever.  Maybe that's just a bug, though.  In fact I 
think I'll go file it as one right now.

--bb
August 30, 2007
Re: class extensions
Chris Nicholson-Sauls wrote:
> Bill Baxter wrote:
>> kris wrote:
>>> Lutger wrote:
>>>> kris wrote:
>>

>> 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.
> 

Maybe even just use a semi-colon instead of comma in the arg list?
  size_t indexOf(T)(T[] array; T elem) { ... }
  ulong area (IShape shp;) { ... }
  void unique (ref T[] array; T) () { ... }

--bb
August 30, 2007
Re: class extensions
Bill Baxter wrote:
> Chris Nicholson-Sauls wrote:
>> Bill Baxter wrote:
>>> kris wrote:
>>> 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.
>>
> 
> Maybe even just use a semi-colon instead of comma in the arg list?
>   size_t indexOf(T)(T[] array; T elem) { ... }
>   ulong area (IShape shp;) { ... }
>   void unique (ref T[] array; T) () { ... }
> 
> --bb

I like that syntax; something similiar is used in mathematics on 
occasion.  Simple and elegant.

Thanks,
Nathan Reed
August 31, 2007
Re: class extensions
Nathan Reed wrote:
> Bill Baxter wrote:
>> Chris Nicholson-Sauls wrote:
>>> Bill Baxter wrote:
>>>> kris wrote:
>>>> 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.
>>>
>>
>> Maybe even just use a semi-colon instead of comma in the arg list?
>>   size_t indexOf(T)(T[] array; T elem) { ... }
>>   ulong area (IShape shp;) { ... }
>>   void unique (ref T[] array; T) () { ... }
>>
>> --bb
> 
> I like that syntax; something similiar is used in mathematics on 
> occasion.  Simple and elegant.
> 
> Thanks,
> Nathan Reed

Agreed.  I believe the use of semicolons within params was once suggested for another 
purpose, ages ago, and (obviously) went nowhere.  Maybe this suggestion will be a bit more 
lucky.

-- Chris Nicholson-Sauls
August 31, 2007
Re: class extensions
Alexander Panek wrote:
> 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)

Perhaps, but even without interchangeability warning signs go up for me 
if you have a method and a function that have the same signature.
Next ›   Last »
1 2 3
Top | Discussion index | About this forum | D home