New Syntax for Extension Methods in Delphi Prism
Ever since Extension Methods have been introduced in .NET 3.5, we’ve been pondering on a proper syntax to allow developers to define their own. C# uses an awkward syntax where it uses the this keyword (C#’s equivalent of self) as name of the first parameter. But that felt wrong. For one, it’s a very C-like thing to do (having an obscure syntax that is not really discoverable or understandable, it ranks right up there with =0 for abstract methods in C++), for another, the fact that methods receive a self pointer as first parameter shoud be an implementation detail of the language (or runtime), not a syntax feature.
Another idea was to simply allow a new extension directive to be appended to a method declaration (similar to virtual or similar constructs). But that too felt wrong.
So what we did, for the time being, was to not provide any special syntax at all, and let people simply define extension methods “manually”, by applying the appropriate attributes. Given that extension methods are consumed (which we have always supported) much more often than defined, we figured this was a good enough compromise, for the time being.
Then, a couple months back, i was doing some language research, among with was watching the introduction video for Go, the new system language created by Google. While in general Go’s syntax felt, to me, like C/C++ beaten with the ugly stick (no offense), it introduced some nice concepts, and one thing that struck me was how easily Go allowed to declare new methods for a class.
This, i thought, was how extension methods should work like, in Prism. An extension method, ultimately, should not have to be part of some arbitrary class that has nothing to do with that method or with the class you are extending. Forcing extension methods into a class syntax is not proper Object Orientation – on the contrary, it’s an abuse of OO syntax. And why shouldn’t you be able to just go ahead and declare the method – without having to learn some awkward syntax or rules?
i decided you should, and after convincing Carlo to do the actual implementation, i am happy to let you know you that starting with the upcoming Spring release of Delphi Prism, you can now define extension methods by, well, just defining them.
extension method Int32.Twice: Int32; begin result := self*2; end;
If we overlook the new extension keyword for now, this looks like a regular method on Int32 – which, essentially, it is. There is no need to define an awkward “self” parameter; you just specify the method name prefixed with the type – as you’ve done thousands of times when writing your own classes – and the compiler takes it from there.
Only the extension keyword indicates that Int32 is not really your own class, but that you’re extending a class defined somewhere else.
This new syntax should make it much more convenient and attractive to define new extension methods, when and where you need them – without all the overhead of a class declaration.
Of course this works on more complex types, as well; the following complete program prints the square of all numbers between 0 and 100 – not by squaring the numbers, but by squaring the sequence of numbers. (It also shows off two other new language features we haven’t talked about yet ;)
namespace ExtensionMethods; interface uses System.Collections.Generic, System.Linq; extension method IEnumerable<Int32>.Squared: IEnumerable<Int32>; implementation extension method IEnumerable<Int32>.Squared: IEnumerable<Int32>; begin result := for each value in self yield value*value; end; begin var values := for i: Int32 := 0 to 100 yield i; for each i in values.Squared do Console.WriteLine(i); end.
Let me know what you think!