Skip to content

Generics and type information

Jonathan edited this page Mar 13, 2018 · 1 revision

In Firefly, generics are always kept, the way this information is stored depends on the target. For the JVM, generics must be provided as function arguments (or constructor arguments).

Generics

Generic classes/interfaces/enums/types...

interface List<T> {
}

class LinkedListImpl<T> : List<T> {
}

enum Option<T> {
    Some(val value: T),
    None
}

type Container<T> {
    val value: T
}

Operating on generic types and generic values

Firefly does not allow you to operate on generic values directly such as:

fun <T> add(f: T, s: T): T { f + s }

Note: This fails with generic type T does not implement + function.

Instead you should explicitly specify that the type T implements + or make it dynamic:

fun <T: dynamic> add(f: T, s: T): T { f + s } // + invoked dynamically at runtime
fun <T: AddOp> add(f: T, s: T): T { f + s } // + invoked statically, but may also be invoked dynamically depending on the case

Constructor invocation

Sometimes you want to invoke the constructor of the generic type, to do this you should declare a Type with the constructor and specify that the generic implements the type:

type Example {
    fun new(name: String, count: Int): Example
}

fun <T: Example> factory(): T { T.new("x", count++) }

Generic Type Information

fun <T> info(): FireflyType = type<T>()

fun <E> gens() {
    info<List<String>>() // FireflyType.concrete(List).of(String)
    info<Map<String, Int>>() // FireflyType.concrete(Map).of(String).and(Int)
    info<Map<String, Map<Int, E>>>() // FireflyType.concrete(Map).of(String).and(FireflyType.concrete(Map).of(Int).and("E"))
    info<E>() // FireflyType.type(type<E>())

    // From firefly classes:
    val map = HashMap<String, Int>()
    typeOf(map) // FireflyType.concrete(HashMap).of(String).and(Int)

    // For Java Types
    val javaMap = java.util.HashMap<String, Int>()
    typeOf(map) // FireflyType.java(HashMap).of(FireflyType.javaVariable("K")).and(FireflyType.javaVariable("V"))
}
Clone this wiki locally