View mode: basic / threaded / horizontal-split · Log in · Help
May 18, 2008
Re: Proposal: Extension Methods
Nick Sabalausky wrote:
> I was just looking through the documentation on some of the Phobos stuff 
> that's new in D2, and at pipe! and compose! in particular. This is kind of 
> nice (from docs):
> 
> int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");
> 
> Not to nag about extension methods (well, ok, yes: to nag ;) ), but with 
> extension methods (regardless if they're explicit or implicit), that could 
> be cleaned up to:
> 
> int[] a = "file.txt".readText().split().map!(to!(int)))();

Or: auto a = "file.txt".readText.split.map!(to!(int)));

Now, since "file.txt" is an array, readText returns an array, and split 
returns an array, you can currently do this. Were any of those a class, 
struct, or scalar, you'd be SOL until uniform call syntax is implemented.

I wonder if uniform call syntax could be used the opposite way:
class A
{
	void foo(){}
}
foo(new A);
May 18, 2008
Re: Proposal: Extension Methods
Nick Sabalausky Wrote:

> "Nick Sabalausky" <a@a.a> wrote in message 
> news:g08fha$2e5$1@digitalmars.com...
> >I thought I had seen discussion on something like this back when the 
> >"Functions as Array Properties" feature was introduced, but I just did a 
> >search and didn't see much of anything. So sorry if this has been discussed 
> >to death before.
> >
> > I propose adding to D a feature that C# calls extension methods. These are 
> > similar to D's "Functions as Array Properties", but provide more control 
> > and flexibility.
> >
> > For any function that's not a member of a class (and maybe also static 
> > member functions of classes), if you add the modifier "extend" or "this" 
> > to first argument of the function declaration like this:
> >
> > // Normal Function
> > void Foo(MyClass arg) {/*...*/}
> >
> > // Extension Method (I'm proposing either of these, but not both):
> > void Foo(this MyClass arg) {/*...*/} // C#-style
> > void Foo(extend MyClass arg) {/*...*/} // Might be more readable
> >
> > (Although, there wouldn't actually be overloading based soley on whether 
> > or not it's declared as an extension method. (Or would there? Probably 
> > not.))
> >
> > Then that allows you to call Foo like this:
> >
> > auto obj = new MyClass();
> >
> > // Always allowed
> > Foo(obj);
> >
> > // Allowed if and only if Foo has been declared
> > // using the above extension method syntax.
> > // But regardless, Foo never has access to private members
> > // of MyClass, since it still isn't a true member.
> > obj.Foo();
> >
> > This should also be allowed for primitives:
> >
> > void Foo(extend int arg);
> > int myInt = 7;
> > myInt.Foo();
> > 5.Foo(); // Might interfere with parsing of floating-point literals, 
> > though.
> >
> > This has two advantages over the current "Functions as Array Properties" 
> > feature:
> >
> > 1. It supports more than just arrays (obviously).
> > 2. The special syntax is only available if the function's author intends 
> > it as a non-member "extension" to the given type.
> >
> > Possible modifications to this proposal:
> >
> > - If advantage #2 is deemed to be an unwarranted concern, I'd be happy to 
> > at least have the current "Functions as Array Properties" feature extended 
> > to all types, not just arrays.
> >
> > - Maybe declaring a function as an extension method would *require* it to 
> > be called using extension method syntax. Although under this arrangement, 
> > if you wanted a function to be callable via either syntax (but would this 
> > ability really be desirable?), that would require a function overload or a 
> > messy kludge like using "maybe_extend" instead of "extend".
> >
> 
> I was just looking through the documentation on some of the Phobos stuff 
> that's new in D2, and at pipe! and compose! in particular. This is kind of 
> nice (from docs):
> 
> int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");
> 
> Not to nag about extension methods (well, ok, yes: to nag ;) ), but with 
> extension methods (regardless if they're explicit or implicit), that could 
> be cleaned up to:
> 
> int[] a = "file.txt".readText().split().map!(to!(int)))();
> 
> Granted, this doesn't actually create a new composite function. But for 
> cases like this one where a reusable composite function isn't needed, it 
> increases readablity quite a bit.
> 
> It would also allow extra paramaters to be specified without having to turn 
> them into template parameters:
> 
> int[] a = "file.csv".readText().split(",").map!(to!(int)))();

This is big problem with functional style in D! D does not have currying. Unfortunate you can not write split(",") and obtain a new function. Maybe language in future can accept split(_, ",") meaning function that takes one argument and passes to split in first position and "," in second position. Dee Girl
May 18, 2008
Re: Proposal: Extension Methods
"Dee Girl" <deegirl@noreply.com> wrote in message 
news:g0pfva$1cqb$1@digitalmars.com...
> Nick Sabalausky Wrote:
>> It would also allow extra paramaters to be specified without having to 
>> turn
>> them into template parameters:
>>
>> int[] a = "file.csv".readText().split(",").map!(to!(int)))();
>
> This is big problem with functional style in D!

Yea, I kinda thought that would cause a problem with functional style. But 
like I said, if you need a functional style, you can still just use pipe! or 
compose!.

> D does not have currying. Unfortunate you can not write split(",") and 
> obtain a new function. Maybe language in future can accept split(_, ",") 
> meaning function that takes one argument and passes to split in first 
> position and "," in second position. Dee Girl

Couldn't you do something like that with templates? It wouldn't be as pretty 
as built-in currying support though.
May 18, 2008
Re: Proposal: Extension Methods
"Chris Wright" <dhasenan@gmail.com> wrote in message 
news:g0pcpm$14f2$1@digitalmars.com...
> Nick Sabalausky wrote:
>> I was just looking through the documentation on some of the Phobos stuff 
>> that's new in D2, and at pipe! and compose! in particular. This is kind 
>> of nice (from docs):
>>
>> int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");
>>
>> Not to nag about extension methods (well, ok, yes: to nag ;) ), but with 
>> extension methods (regardless if they're explicit or implicit), that 
>> could be cleaned up to:
>>
>> int[] a = "file.txt".readText().split().map!(to!(int)))();
>
> Or: auto a = "file.txt".readText.split.map!(to!(int)));
>
> Now, since "file.txt" is an array, readText returns an array, and split 
> returns an array, you can currently do this. Were any of those a class, 
> struct, or scalar, you'd be SOL until uniform call syntax is implemented.
>

Heh, true, I wasn't thinking about that example using all arrays. Bad 
example :)

Does eliminating the no-argument parentheses like that currently work, or 
are you proposing that?

> I wonder if uniform call syntax could be used the opposite way:
> class A
> {
> void foo(){}
> }
> foo(new A);

That's been my assumption. After all, isn't that what happens 
behind-the-scenes anyway (ie, "this" being passed as a hidden first 
parameter)? (I know it is in C++)

But, I wonder if disallowing that might eliminate some of the concerns I had 
about "uniform call syntax"/"implicit extension methods". I'll have to think 
about that.
May 19, 2008
Re: Proposal: Extension Methods
Nick Sabalausky wrote:
> "Chris Wright" <dhasenan@gmail.com> wrote in message 
> news:g0pcpm$14f2$1@digitalmars.com...
>> Or: auto a = "file.txt".readText.split.map!(to!(int)));
>>
>> Now, since "file.txt" is an array, readText returns an array, and split 
>> returns an array, you can currently do this. Were any of those a class, 
>> struct, or scalar, you'd be SOL until uniform call syntax is implemented.
>>
> 
> Heh, true, I wasn't thinking about that example using all arrays. Bad 
> example :)
> 
> Does eliminating the no-argument parentheses like that currently work, or 
> are you proposing that?

It works currently. In dunit assertions, for instance, you can do:
expect(foo).not.sameAs(bar);
// equivalent to expect(foo).not().sameAs(bar);

>> I wonder if uniform call syntax could be used the opposite way:
>> class A
>> {
>> void foo(){}
>> }
>> foo(new A);
> 
> That's been my assumption. After all, isn't that what happens 
> behind-the-scenes anyway (ie, "this" being passed as a hidden first 
> parameter)? (I know it is in C++)
> 
> But, I wonder if disallowing that might eliminate some of the concerns I had 
> about "uniform call syntax"/"implicit extension methods". I'll have to think 
> about that.

I'm not sure how you would explicitly use the class method rather than 
the free function if it were allowed. I just thought it was amusing.
May 19, 2008
Re: Proposal: Extension Methods
Chris Wright wrote:
> Nick Sabalausky wrote:
>> "Chris Wright" <dhasenan@gmail.com> wrote in message 
>> news:g0pcpm$14f2$1@digitalmars.com...
>>> Or: auto a = "file.txt".readText.split.map!(to!(int)));
>>>
>>> Now, since "file.txt" is an array, readText returns an array, and 
>>> split returns an array, you can currently do this. Were any of those 
>>> a class, struct, or scalar, you'd be SOL until uniform call syntax is 
>>> implemented.
>>>
>>
>> Heh, true, I wasn't thinking about that example using all arrays. Bad 
>> example :)
>>
>> Does eliminating the no-argument parentheses like that currently work, 
>> or are you proposing that?
> 
> It works currently. In dunit assertions, for instance, you can do:
> expect(foo).not.sameAs(bar);
> // equivalent to expect(foo).not().sameAs(bar);
> 

Oops, that works because expect is a UDT. It doesn't work with array 
stuff. My mistake.
June 10, 2008
Re: Proposal: Extension Methods
Nick Sabalausky wrote:
> I thought I had seen discussion on something like this back when the 
> "Functions as Array Properties" feature was introduced, but I just did a 
> search and didn't see much of anything. So sorry if this has been discussed 
> to death before.
> 
> I propose adding to D a feature that C# calls extension methods. These are 
> similar to D's "Functions as Array Properties", but provide more control and 
> flexibility.
> 
> For any function that's not a member of a class (and maybe also static 
> member functions of classes), if you add the modifier "extend" or "this" to 
> first argument of the function declaration like this:
> 
> // Normal Function
> void Foo(MyClass arg) {/*...*/}
> 
> // Extension Method (I'm proposing either of these, but not both):
> void Foo(this MyClass arg) {/*...*/} // C#-style
> void Foo(extend MyClass arg) {/*...*/} // Might be more readable
> 
> (Although, there wouldn't actually be overloading based soley on whether or 
> not it's declared as an extension method. (Or would there? Probably not.))
> 
> Then that allows you to call Foo like this:
> 
> auto obj = new MyClass();
> 
> // Always allowed
> Foo(obj);
> 
> // Allowed if and only if Foo has been declared
> // using the above extension method syntax.
> // But regardless, Foo never has access to private members
> // of MyClass, since it still isn't a true member.
> obj.Foo();
> 
> This should also be allowed for primitives:
> 
> void Foo(extend int arg);
> int myInt = 7;
> myInt.Foo();
> 5.Foo(); // Might interfere with parsing of floating-point literals, though.
> 
> This has two advantages over the current "Functions as Array Properties" 
> feature:
> 
> 1. It supports more than just arrays (obviously).
> 2. The special syntax is only available if the function's author intends it 
> as a non-member "extension" to the given type.
> 
> Possible modifications to this proposal:
> 

Overall it seems like an interesting idea. Note: I would prefer the syntax:
  void Foo(MyClass this, int a, ...) {...

Some other details might need to be worked out, but overall it looks sound.

> - If advantage #2 is deemed to be an unwarranted concern, I'd be happy to at 
> least have the current "Functions as Array Properties" feature extended to 
> all types, not just arrays.
> 

For the sake of consistency, I think it would be best if rule #2 remains.

> - Maybe declaring a function as an extension method would *require* it to be 
> called using extension method syntax. Although under this arrangement, if 
> you wanted a function to be callable via either syntax (but would this 
> ability really be desirable?), that would require a function overload or a 
> messy kludge like using "maybe_extend" instead of "extend".
> 
> 

I would prefer not. In fact, I think it would be useful that even class 
methods would be callable with an explicit 'this' parameter, like this:

  class Foo {
    void func(int a);
  }

  auto foo = new Foo();
  Foo.func(foo, 2); // same as foo.func(2);

The benefit of this, is to be able to use Foo.func as a function 
pointer, and thus we would have a feature similar to C++'s member 
functions, as well as the ability to call a specific override in a 
method override lineage.


-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Next ›   Last »
1 2
Top | Discussion index | About this forum | D home