www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Proposal: Extension Methods

reply "Nick Sabalausky" <a a.a> writes:
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".
May 11 2008
next sibling parent reply janderson <askme me.com> writes:
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:
 
 - 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".
 
 

Walter talked about the proposal for interchangeable method/functions. It was talked about at the D conference. I'm not sure how much resistance he got to the idea. I'm a big fan on interchangeable function/methods without the additional syntax as it would push the flexibility to the user rather then the lib designer. I have mentioned it several times. -Joel
May 11 2008
parent reply "Nick Sabalausky" <a a.a> writes:
"janderson" <askme me.com> wrote in message 
news:g08j47$8cs$1 digitalmars.com...
 Walter talked about the proposal for interchangeable method/functions. It 
 was talked about at the D conference.  I'm not sure how much resistance he 
 got to the idea.

 I'm a big fan on interchangeable function/methods without the additional 
 syntax as it would push the flexibility to the user rather then the lib 
 designer.  I have mentioned it several times.

Maybe someone can point out that I'm worrying over nothing, but here's my main concern about that: Unless I misunderstand the "interchangeable methods/functions" concept, that means that the following code would result in conflict issues with "Foo": // Note: sample code untested module moduleA { class A { public void Foo() {} } void Bar() {} } module moduleB { import moduleA; void Foo(ref A a) {} void Bar() {} void main(char[][] args) {} } In this example, there is a conflict with Bar(). But this is OK, since, in main() we can disambiguate like (I might be forgetting the details here, but it's something like this): moduleA.Bar(); // moduleA's Bar() .Bar(); // moduleB's Bar() // On a totally separate note, what does this do? // Does this assume one Bar() or the other, // or is it disallowed due to ambiguity? Bar(); So with Bar() we're ok. But how would you disambiguate Foo() when using member function syntax? auto a = new A(); // moduleA: a.moduleA.Foo(); // Makes it seem like "moduleA" belongs to "a" moduleA.a.Foo(); // Makes it seem like "a" belongs to "moduleA" a.A.Foo(); // Makes it seem like "A" is a member of "a" A.a.Foo(); // Makes it seem like "a" is a static member of "A" a.(moduleA.Foo)(); // Kinda ugly, but maybe? a.(A.Foo)(); // Kinda ugly, but maybe? // moduleB: a..Foo(); // As Earnest P. Worrell would say, "Eeeewwww..." .a.Foo(); // Makes it seem like the scope resolution // operator is referring to "a" instead of "Foo" a.(.Foo)(); // Kinda ugly, but maybe? Seems to me you could solve that three ways, none of which seem ideal: 1. Disallow member function syntax when a conflict like this exists. So all of a sudden, I can't call A's own member function with member function syntax. Yuck. 2. Force member function syntax to mean moduleA's Foo() and non-member syntax to mean moduleB's Foo(). But this could result in accidentally calling the wrong Foo(), especially when people are accustomed to being able to use "obj.Func();" and "Func(obj);" interchangeably. 3. Generate a "function redefined" compile-time error. But this is inconsistent with Bar().
May 12 2008
next sibling parent janderson <askme me.com> writes:
Nick Sabalausky wrote:
 "janderson" <askme me.com> wrote in message 
 news:g08j47$8cs$1 digitalmars.com...
 Walter talked about the proposal for interchangeable method/functions. It 
 was talked about at the D conference.  I'm not sure how much resistance he 
 got to the idea.

 I'm a big fan on interchangeable function/methods without the additional 
 syntax as it would push the flexibility to the user rather then the lib 
 designer.  I have mentioned it several times.

Maybe someone can point out that I'm worrying over nothing, but here's my main concern about that: Unless I misunderstand the "interchangeable methods/functions" concept, that means that the following code would result in conflict issues with "Foo": // Note: sample code untested module moduleA { class A { public void Foo() {} } void Bar() {} } module moduleB { import moduleA; void Foo(ref A a) {} void Bar() {} void main(char[][] args) {} } In this example, there is a conflict with Bar(). But this is OK, since, in main() we can disambiguate like (I might be forgetting the details here, but it's something like this): moduleA.Bar(); // moduleA's Bar() .Bar(); // moduleB's Bar() // On a totally separate note, what does this do? // Does this assume one Bar() or the other, // or is it disallowed due to ambiguity? Bar(); So with Bar() we're ok. But how would you disambiguate Foo() when using member function syntax? auto a = new A(); // moduleA: a.moduleA.Foo(); // Makes it seem like "moduleA" belongs to "a" moduleA.a.Foo(); // Makes it seem like "a" belongs to "moduleA" a.A.Foo(); // Makes it seem like "A" is a member of "a" A.a.Foo(); // Makes it seem like "a" is a static member of "A" a.(moduleA.Foo)(); // Kinda ugly, but maybe? a.(A.Foo)(); // Kinda ugly, but maybe? // moduleB: a..Foo(); // As Earnest P. Worrell would say, "Eeeewwww..." .a.Foo(); // Makes it seem like the scope resolution // operator is referring to "a" instead of "Foo" a.(.Foo)(); // Kinda ugly, but maybe? Seems to me you could solve that three ways, none of which seem ideal: 1. Disallow member function syntax when a conflict like this exists. So all of a sudden, I can't call A's own member function with member function syntax. Yuck. 2. Force member function syntax to mean moduleA's Foo() and non-member syntax to mean moduleB's Foo(). But this could result in accidentally calling the wrong Foo(), especially when people are accustomed to being able to use "obj.Func();" and "Func(obj);" interchangeably. 3. Generate a "function redefined" compile-time error. But this is inconsistent with Bar().

If the code has been multiply defined, the compiler should respond that it does not know what version to use and ask for a qualifier. What that qualifier is I don't know. Perhaps: Foo((a)); and (a).Foo(); -Joel
May 12 2008
prev sibling parent janderson <askme me.com> writes:
Nick Sabalausky wrote:
 "janderson" <askme me.com> wrote in message 
 news:g08j47$8cs$1 digitalmars.com...
 Walter talked about the proposal for interchangeable method/functions. It 
 was talked about at the D conference.  I'm not sure how much resistance he 
 got to the idea.

 I'm a big fan on interchangeable function/methods without the additional 
 syntax as it would push the flexibility to the user rather then the lib 
 designer.  I have mentioned it several times.

Maybe someone can point out that I'm worrying over nothing, but here's my main concern about that: Unless I misunderstand the "interchangeable methods/functions" concept, that means that the following code would result in conflict issues with "Foo": // Note: sample code untested module moduleA { class A { public void Foo() {} } void Bar() {} } module moduleB { import moduleA; void Foo(ref A a) {} void Bar() {} void main(char[][] args) {} } In this example, there is a conflict with Bar(). But this is OK, since, in main() we can disambiguate like (I might be forgetting the details here, but it's something like this): moduleA.Bar(); // moduleA's Bar() .Bar(); // moduleB's Bar() // On a totally separate note, what does this do? // Does this assume one Bar() or the other, // or is it disallowed due to ambiguity? Bar(); So with Bar() we're ok. But how would you disambiguate Foo() when using member function syntax? auto a = new A(); // moduleA: a.moduleA.Foo(); // Makes it seem like "moduleA" belongs to "a" moduleA.a.Foo(); // Makes it seem like "a" belongs to "moduleA" a.A.Foo(); // Makes it seem like "A" is a member of "a" A.a.Foo(); // Makes it seem like "a" is a static member of "A" a.(moduleA.Foo)(); // Kinda ugly, but maybe? a.(A.Foo)(); // Kinda ugly, but maybe? // moduleB: a..Foo(); // As Earnest P. Worrell would say, "Eeeewwww..." .a.Foo(); // Makes it seem like the scope resolution // operator is referring to "a" instead of "Foo" a.(.Foo)(); // Kinda ugly, but maybe? Seems to me you could solve that three ways, none of which seem ideal: 1. Disallow member function syntax when a conflict like this exists. So all of a sudden, I can't call A's own member function with member function syntax. Yuck. 2. Force member function syntax to mean moduleA's Foo() and non-member syntax to mean moduleB's Foo(). But this could result in accidentally calling the wrong Foo(), especially when people are accustomed to being able to use "obj.Func();" and "Func(obj);" interchangeably. 3. Generate a "function redefined" compile-time error. But this is inconsistent with Bar().

Actually maybe using alias like we do now will do that job. -Joel
May 12 2008
prev sibling next sibling parent terranium <spam here.lot> writes:
It seems like C# is so young, that D was mostly done when it appeared.
May 12 2008
prev sibling next sibling parent reply Fawzi Mohamed <fmohamed mac.com> writes:
On 2008-05-12 06:03:01 +0200, "Nick Sabalausky" <a a.a> said:

 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 find this kind of extensions nice, they allow to work around library misdesign (or to handle special cases) in a much better way. Dynamic language often can do it. A static language language that had the idea of a posteriori extension very well developed: http://www.aldor.org/docs/HTML/chap10.html (the language itself is basically dead but for other reasons) The question is how difficult is their implementation, and how useful they really are, as these can lead also to bad design if overused, but well used they are really nice. Fawzi
May 12 2008
parent reply "Nick Sabalausky" <a a.a> writes:
"Fawzi Mohamed" <fmohamed mac.com> wrote in message 
news:g09ivq$6bk$1 digitalmars.com...
 I find this kind of extensions nice, they allow to work around library 
 misdesign (or to handle special cases) in a much better way.
 Dynamic language often can do it.
 A static language language that had the idea of a posteriori extension 
 very well developed:
 http://www.aldor.org/docs/HTML/chap10.html
 (the language itself is basically dead but for other reasons)
 The question is how difficult is their implementation, and how useful they 
 really are, as these  can lead also to bad design if overused, but well 
 used they are really nice.

I didn't read that page very closely, but it sounds like the extensions in Aldor are true members of the class they're extending and able to access private members? If so, that's the first time I've seen that in a static language (Which is kind of interesting). It also sounds kind of like partial classes, but with the original class not needing to be declared as partial. Maybe it's just an unsubstantiated gut feeling, but that stikes me as either breaking encapsulation, or possibly causing trouble for dynamic linking (ie, one assembly's version of the class has the methods, and another assembly's version doesn't - but then, couldn't that affect C#'s partial classes too? I wonder how they solved it?), or otherwise reducing some of the benefits of strong static typing.
May 12 2008
parent Pragma <eric.t.anderton gmail.com> writes:
Nick Sabalausky Wrote:

 Maybe it's just an unsubstantiated gut feeling, but that stikes me as either 
 breaking encapsulation, or possibly causing trouble for dynamic linking (ie, 
 one assembly's version of the class has the methods, and another assembly's 
 version doesn't - but then, couldn't that affect C#'s partial classes too? I 
 wonder how they solved it?), or otherwise reducing some of the benefits of 
 strong static typing. 
 

IMO, yes it does break encapsulation, but it shouldn't disrupt dynamic linking. The former is really more of a "best practice" kind of thing. My feeling on that is that a language always generates a wart when it tries to hold too tightly to such things since there's always a case where it doesn't apply. Perhaps "extension methods" are one of those cases? As to the latter, dynamic linking, I've played around a lot in this area. Dynamically linking against anything but an interface is a bad idea for a few reasons; obviously interfaces wouldn't apply with "extension methods". But if you are coding against a given implementation of a class or struct, then there is no problem since the linked library should have or require the same class or struct. For dynamic linking and working with classes/structs, the real problem is: do the host program and the dynamic library have access to the same *version* of the class/struct in question? If not, then there's a mismatch between the binary size and/or vtable layout of the items in question. And that's clearly not a problem that is limited to our hypthotetical "extension methods", so again, there shouldn't be any new technical problems introduced, were they implemented. - Pragma
May 12 2008
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"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)))(); Maybe that might break functional-style code if that's what the coder is going for (not sure, my functional experience is limited), but in that case they can still fall back on pipe!.
May 18 2008
next sibling parent reply Chris Wright <dhasenan gmail.com> writes:
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
parent reply "Nick Sabalausky" <a a.a> writes:
"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 18 2008
parent reply Chris Wright <dhasenan gmail.com> writes:
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 18 2008
parent Chris Wright <dhasenan gmail.com> writes:
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.
May 18 2008
prev sibling parent reply Dee Girl <deegirl noreply.com> writes:
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
parent "Nick Sabalausky" <a a.a> writes:
"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
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
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
Jun 10 2008