Two faces of extensions

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:

  1. the function is placed directly in (any) namespace,
  2. the modifier is extension,
  3. 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).

Tagged ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: