Type Parameters

Any object, including prototypes, can be parameterized with type parameters. These are expressions resolving to other objects, which can be used just like macros inside the object or its fields’ definitions.

A type parameter value can be specified (overridden) when inheriting an object, which has a type parameter.

For example, a link object has a type parameter called interface representing a link interface. It can be specified like this:

Integer link :=> integer` link

Type Definition

Type parameters can be declared inside a special type definition block of phrase or object construction expression. The syntax is:

<prefix> '#' '(' <type definition> ')' <phrase parts>

where <type definition> consists of a sentences containing type parameters declarations in the form similar to field declarations:

<name> [ ['@' ['('] <ascendant> [')'] ] | ':' ] '=' <type>

where:

  • <name> is type parameter name;
  • <ascendant> is a reference to an object’s ascendant, the overridden type parameter is present in;
  • <type> is a reference to an object, used as initial value; can be a macro expansion.

Each of such declarations declares a new type parameter or overrides an existing one, and provides the initial value for it.

The order of type parameters declaration is significant.

See also how the type definition is declared in a standalone file.

Type Parameters Usage

Each type parameter can be used like any other macro. E.g. it can be expanded. There are differences though:

  • Unlike ordinal fields, the type parameter can be accessed even if it is defined inside a prototype.
  • The type parameter may refer to other type parameter of the object, or other object, but can not refer the object it is defined in, or the fields of this object.
  • The type parameter can not be overridden outside of the type definition.
  • Type parameters can be passed to the newly constructed object with a [type arguments][#type-arguments] expression.
  • Type parameters can be specified either as type arguments, or inside a type definition, but not both.

Type Arguments

Type arguments is a shorter way to specify the type parameters. The syntax is:

<argument> '`' [ <argument> '`' ... ] <type>

where:

Type arguments are substituted as type parameter values in the order of parameters declaration within a type definition. If the number of arguments passed is less than the number of parameters declared, the rest of parameter values won’t change.

Here are some examples:

integer` link               ~~ Link to integer.
string` array               ~~ Array of strings.
string` array` link         ~~ Link to array of strings.
(string` array)` link       ~~ The same as above.
(string, integer` row)` map ~~ Map of string keys to integer row values.

Examples

Here is an example illustrating the type parameters usage with map interface:

Map :=> void #( 
  ~~~
  A key/value map interface.
  ~~~
  Key type := void   ~~ Key type parameter.
  Value type := void ~~ Value type parameter.
) (
  Get :=> #value type` link (
    ~~~
    Returns a value by its key.
    ~~~
    Key :=< #key type` link  ~~ A key of the value to find.
  )
)

Hash map :=> map (
  ~~~
  Hash map implementation here.
  ~~~
)

Integers by strings := (string, integer)` hash map
~~ A hash map with string keys and integer values.

Integers by strings: get (Key = "one")