logo

Programming Languages - Generics

Last Updated: 2024-01-21

Generics: Similar to the way a function takes parameters with unknown values to run the same code on multiple concrete values, functions can take parameters of some generic type instead of a concrete type.

Rust: Code doesn’t run any slower using generic types than it would with concrete types.

Rust accomplishes this by performing monomorphization of the code that is using generics at compile time. Monomorphization is the process of turning generic code into specific code by filling in the concrete types that are used when compiled. the compiler looks at all the places where generic code is called and generates code for the concrete types the generic code is called with.

By Language

Go

Generic functions:

func Index[T comparable](s []T, x T) int

Generic types:

type List[T any] struct {
	next *List[T]
	val  T
}

Rust

// in function
fn foo<T>(list: &[T]) -> T {
}

// in struct
struct Point<T> {
    x: T,
    y: T,
}

// in enum
enum Option<T> {
    Some(T),
    None,
}

// in method
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

Java

Java Type erasure: enforcing type constraints only at compile time and discarding the element type information at runtime.

Kotlin

Like Java's, Kotlin's generics are not retained at runtime: objects do not carry information about actual type arguments passed to their constructors. For example, ArrayList<Integer>() is indistinguishable from ArrayList<Character>().