func first(v: T[]): Result<T, Bool> {
if len(v) > 0 {
return Result.Ok(v[0])
}
return Result.Error(false)
}
proc main(): void {
a := first([1, 2, 3]) // first_Int
b := first(["x", "y"]) // first_Str, uma cópia separada
echo "{a} {b}"
}type Box {
items: T[dyn]
label: Str
}
type Either {
Left { left: A }
Right { right: B }
}
proc main(): void {
Box<Str> people = Box(["ada", "grace"], "people")
Box<Int> counts = Box([1, 2, 3], "counts")
Either<Str, Int> answer = Either.Right(42)
echo "{people.label}: {people.items}"
echo "{counts.label}: {counts.items}"
if answer is Either.Right(n) { echo n }
}Um nome em uma assinatura que não é nem um tipo nativo nem um declarado é uma variável de tipo, e ele torna o chamável genérico. Uma variável é fixada por onde aparece entre os parâmetros — inclusive dentro do próprio tipo de função de um parâmetro. Nada nela é dinâmico: toda chamada é resolvida quando o programa compila, e uma cópia concreta é escrita para cada conjunto distinto de argumentos de tipo — first_Str, first_Int — sem boxing e sem despacho. Um tipo pode receber variáveis do mesmo jeito, e é escrito com elas preenchidas: Box<Str>, Either<Str, Int>.
Vale saber:
func greet(u: Usr): Str é genérico, e aceita qualquer coisa. Confira a grafia quando uma função aceitar mais do que deveria.broken_Int.Either<Str, Int> answer = Either.Right(42) — já que a variante sozinha não diz o que o outro lado guarda.