Reified Parameters

Reify parameters to allow us to use Generics at runtime.

// Since Generics are erased at runtime then any Generic parameters that are passed to functions cannot determine which type it was invoked with
// Reification is ONLY useful when wanting to check the data type in a function
// Can't mark classes, properties or non-inline functions as reified
fun main() {

    val mixedList: List<Any> = listOf("string", 1, BigDecimal(22.5), "fall", BigDecimal(-349654.345))
    val bigDecimalsOnly = getElementsOfType2<BigDecimal>(mixedList) // Type in <> can be changed to whatever desired
    println(bigDecimalsOnly)
}

//fun <T> getElementsOfType(list: List<Any>): List<T> {
//    var newList: MutableList<T> = mutableListOf()
//    for (element in list) {
//        if (element is T) { // Will not work as T is erased at compile-time
//            newList.add(element)
//        }
//    }
//    return newList
//}

// This situation can benefit from inline functions as the parameters can be REIFIED - prevents the type from being erased at runtime:
inline fun <reified T> getElementsOfType2(list: List<Any>): List<T> { // Require both inline and reified declarations. By inlining the function the compiler can determine what type the parameter is and substitute it in at compile-time.
    var newList: MutableList<T> = mutableListOf()
    for (element in list) {
        if (element is T) { // Now works
            newList.add(element)
        }
    }
    return newList
}