Generic prototypes with Concepts

A generic prototype in Cyan takes a type (or a generic symbol) as a parameter just like generic classes in Java or template classes in C++:

object Box<T> func init: T value { self.value = value } func mult: T other -> T = self.value * other; // create get and set methods @property var T value end

For each new parameter, a new Box prototype is created (like in C++ and unlike in Java). Therefore, Box<Int> and Box<Float> and two unrelated prototypes.
In method mult: of Box, there is the sending of message * with argument other to field value of type T. That means that T should have a method

func * (T other) -> T

in order to compile correctly.

If the supplied type T in the instantiation, like Box, does not have this method, there is a compilation error:

// String does not define a * method var Box<String> bs;

The error issued is:

The type of the real argument, 'cyan.lang.String', of expression 'other' is not sub-prototype of the type of the formal parameter, 'cyan.lang.Int' in message send with keyword '*' Stack of generic prototype instantiations: main.Box<String> line 8 column 45 main.Program line 11 column 17 func mult: (String other) -> String = self.value * other;

The compiler shows code Box<String> in the error message, which is confusing. A better option is to use metaobject concept:

@concept{* T has [ func * T -> T ] *} object Box<T> func init: T value { self.value = value } func mult: T other -> T = self.value * other; // create get and set methods @property var T value end

Now, the error message is clearer:

A concept associated to generic prototype 'main.Box<String>' expected that method '* String -> String' were in prototype 'cyan.lang.String' Stack of generic prototype instantiations: main.Program line 11 column 17 var b = Box<String>("");