Before we begin and I forget — if you place any extension at the same file the type is defined you have full access to all private members of it. Phew, now we can begin…
External extensions
The idea of external extensions are taken from C# — I simply love it. The extension
keyword and grouping is taken from Swift.
Those are pure syntactic sugar, there is nothing you couldn’t write by yourself using non-extension part of the language.
Micro extensions
Let’s say you have collection of collection of some elements, the common task is to flatten
the data. You cannot add such method to Sequence
type, but external method just fits right in:
extension def flatten<E>(this ~~E) ~E
•••
end
Three things to notice:
- the function is placed directly in (any) namespace,
- the modifier is
extension
,
- there is explicit
this
parameter.
Such extension can be used as a function or as a method:
_ = flatten([[1,2],[3,4]]);
_ = [[1,2],[3,4]].flatten();
Extension types
Here we group the methods and properties into extension type — I save better example for later so let’s use absurd one:
extension class Real
def square Real get => this*this;
def cube Real get => square*this;
end
We didn’t change the source of the type. We just added new properties on the side:
_ = 4.5.square;
_ = 1.7.cube;
Please note in case of extension types, we don’t add explicitly this
parameter and we can only call methods as, well, methods.
Internal extensions
I didn’t have time (and a book) to check in detail how much Skila differs from Swift but it seems there was a different need that drove the idea of this extension, thus Skila extensions are more limited. Currently I am reading about Objective-C — and surprise, surprise — I noticed it supports extensions.
Unlike C++ template specializations you cannot provide customized version of a given method present in a template. You can only add new methods (or properties) which do not exist in a template being extended.
Consider two sequences of some elements. Would it be useful to test whether those sequences are equal?
if [a,b] == [c,d] then
•••
It didn’t work, because Sequence
couldn’t blindly assume its elements support equality test. With our new tool we can add appropriate method. Our first try:
extension interface Sequence<T>
where T refines Equatable;
def ==(cmp ~T) Bool
•••
end
end
With above external extension we can test equality of two sequences in safe manner (this is not true in C# which provides unsafe Equals
— pretty much the same as in dynamic languages).
But is it really all? No — despite we can perform the test, we didn’t change the Sequence
type so we cannot compare a sequence of a sequences of Equatable
elements, because the sequence of Equatable
elements does not inherit Equatable
itself:
%% does not work with above extension
if [[a,b],[i,j]] == [[c,d],[k,l]] then
•••
We need internal extension (specialization):
extension interface Sequence<T> refines Equatable
where T refines Equatable;
refines def ==(cmp ~T) Bool
•••
end
end
What does it mean? A general Sequence
type does not inherit from Equatable
interface (because it cannot), but once we drop something that is Equatable
inside Sequence
type, we get type specialization which does inherit from Equatable
.
There is more — a type which inherits from Sequence
(like !Array
) also behaves in the same way, its general version is not Equatable
, but if you have let’s say array of numbers (which are Equatable
) entire array becomes Equatable
— think of it as one specialization inherits from another specialization.
Specializations can be combined — imaginary example, if we wrote specialization for Sequence
to inherit from X
when elements inherit from X
, and in same manner we did with type Y
what happens if we have Sequence
of elements which derive from X
and Y
at the same time? We will get Sequence
type inheriting from X
and Y
.
The bill? You have to place internal extensions in the same file as type being extended. Also you cannot extend non-template type (it does not make sense in Skila perspective, because there would be no way to discriminate such extension).