Generic Overview

In the Cangjie programming language, "generics" is a common term for parameterized types and functions, in the definitions of which certain types are left unspecified. Those types are specified each time such a generic type or function is used. Essentially, each generic type or function defines a set of regular types or functions, with one entry for each valid combination of those unspecified types.

The most common examples of generic types are container types such as Array<T> or Set<T>. Take the array type as an example. Arrays must be capable of storing elements of different types. At the same time, the set of operations on all arrays is the same and does not depend on their element types. It would be tedious to define a separate array type with all its members for each element type. Fortunately, Cangjie enables us to add a type parameter <T> to the Array type declaration and substitute particular element types instead of T at points of use, thus avoiding code duplication.

In Cangjie, class, interface, struct, and enum types, as well as functions, can be declared with type parameters. In other words, entities of all those kinds can be generic.

For the convenience of subsequent discussion, let's define the following common terms:

  • Type parameter: An identifier denoting a type that needs to be specified during usage of the parameterized type or function. Type parameters are usually enclosed in angle brackets < > and placed immediately after the name of the generic type or function being declared.
  • Type variable: An identifier referencing a type parameter of a generic user type or function within its declaration.
  • Type argument: A particular type specified when a generic type of function is used.
  • Type constructor: A type that requires zero, one, or multiple types as arguments.

For example, a generic list type can be declared and used like this:

class List<T> {
    var elem: Option<T> = None
    var tail: Option<List<T>> = None
}

func sumInt(a: List<Int64>) {  }

In the above code, T in List<T> is a type parameter. T in elem: Option<T> and tail: Option<List<T>> is a type variable. In the parameters of the sumInt function, Int64 in List<Int64> is the type argument of List. List is a type constructor. List<Int64> uses the Int64 type argument to construct a concrete List type for the Int64 type.