Extension methods
See original GitHub issue[@sadmac7000] Most OO languages that don’t allow some extremely irresponsible metaprogramming techniques have a sort of semantic inconsistency when acting on standard types.
Consider the following:
String s = ...
How do we obtain modified forms of the string? If we want the reverse of the string, it would be:
s.reversed
If we want a lower case version of the string we can perform:
s.lowercased
But what if we want a ROT13’d version of the string?
myRot13(s)
We of course have to implement myRot13 ourselves, but I think it is legitimate to ask “why is the syntax for acting upon a string different depending on whether the authors of the language thought to include that action or not?”
Ruby solves this by letting methods be added to classes after runtime, a measure that is in no way appropriate for Ceylon, or compatible with its goals. Other languages allow mixins to be created without consulting the original module author, a more feasible approach, but still one that raises complex questions and jeopardizes Ceylon’s careful attention to type safety and focus on immutability.
I propose a simpler solution. When a function takes only one argument, the keyword “this” may be used as the name of that argument.
String rot13(String this) {
...
}
When a function is declared in this way, the following two forms are equivalent:
rot13(a);
a.rot13
This is the entirety of the change. No further special behavior is required. This function is still a regular function type.
If we want to have the appearance of defining a method, we can use Ceylon’s currying syntax.
String appendReversed(String this)(String other) { ... }
s.appendReversed(s2);
[Migrated from ceylon/ceylon-spec#1146]
Issue Analytics
- State:
- Created 9 years ago
- Reactions:2
- Comments:8 (1 by maintainers)
@almondtools But I don’t think it really helps much, because:
This is an operation that is neither binary compatible (on the JVM), nor source compatible, in any language that I know of, since extension method must be explicitly imported by the source code that uses them.
Even worse, if the method is
formal
(ordefault
), you would break every implementation of the type.Have you thought about the features extension methods could provide for deprecation of methods?
I think it is quite natural that an interface gets to small or to large so it must be extended or pruned. Yet this is a problem if one language version supports a method and another does not.
So if we want to deprecate a method in a new API version:
And if we want to introduce a new method in our new API:
I think extension methods are an promising feature to separate deprecated and experimental features from the core API.