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.
import klyn.collections
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.
import klyn.collections
[10, 20, 30] # ArrayList<Int>
f:[10, 20, 30] # Array<Int>
fs:[10, 20, 30] # ArraySync<Int>
i:[10, 20, 30] # ImmutableList<Int>
{"a": 1, "b": 2} # HashMap<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.
import klyn.collections
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.