Generics
Generics let Klyn preserve strong typing across reusable containers and abstractions. They are central to the collection APIs and to user-defined types that must carry a caller-chosen element type.
public interface Collection<T = Double>:
public add(item as T) as Void
Generic parameters appear between angle brackets and can be referenced throughout the type body.
names = ArrayList<String>()
scores = Map<String, Int>()
Explicit type arguments are especially valuable when the initial state is empty and therefore cannot drive inference on its own.
public class NDArray<T extends AbstractNumber = Double>:
pass
Defaults let a generic API stay concise when one concrete type is overwhelmingly common.
public class NDArray<T extends AbstractNumber = Double>:
pass
A constraint restricts which types may be substituted for the generic parameter.
[10, 20, 30] # ArrayList<Int>
ImmutableList([10, 20, 30]) # ImmutableList<Int>
{"a": 1, "b": 2} # Map<String, Int>
(1, 2, 3) # Tuple<Int, Int, Int>
Literal inference removes boilerplate, but explicit annotations remain the better choice when the surrounding API should communicate a stable type contract.
Klyn now separates immutable homogeneous sequences from tuples:
ImmutableList<T> is exposed through IList<T>,
while Tuple<...Ts> is positional and heterogeneous.
metadata = type(List<Int>)
print(metadata.isGenericInstantiation)
print(metadata.genericParameterCount)
Generic instantiations are visible through reflection, which is useful for tooling and typed framework code.