Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Generics

This chapter describes later generic-language design rather than current V1 compiler behavior.

Current milestone note:

  • generic routines are not part of the implemented V1 typechecker
  • generic types are not part of the implemented V1 typechecker
  • examples here should be read as future V2 design

Types

Generic Functions

Generic programming aims to express one routine over a family of concrete types, with the requirements written explicitly in the signature.

pro max[T: gen](a, b: T): T = {
	result =  a | a < b | b;
};
fun biggerFloat(a, b: flt[32]): flt[32] = { max(a, b) }
fun biggerInteger(a, b: int[64]): int[64] = { max(a, b) }

Generic Types

Generic type surfaces are later-milestone design only. They are shown here as future syntax, not current V1 behavior.

typ container[T: gen, N: int](): obj = {
	var anarray: arr[T,N];
	+fun getsize(): num = { result = N; }
};
var aContainer: container[int, 5] = { anarray = {zero, one, two, three, four}; };

Generic Calls

This chapter does not define an object-dispatch system. If generics later use receiver-qualified routine syntax, that would still be procedural call binding, not virtual methods or inheritance.

std foo: pro = { fun bar(); }

typ[ext] int, str: int, str;

fun (int)bar() = {  }
fun (str)bar() = {  }

pro callBar(T: foo)(value: T) = { value.bar() }             // dispatch with generics
pro barCall( value: foo ) = { value.bar() }                 // dispatch with standards

pro main: int = {
    callBar(2);
    callBar("go");

    barCall(2);
    barCall("go")
}