DEV Community

Espresso
Espresso

Posted on

PartialFunction implemented in Kotlin, inspired by scala


import java.util.function.Function
import java.util.function.Predicate

/**
 * 参考scala的偏函数
 *
 * @see scala.PartialFunction
 */
abstract class PartialFunction<X, Y> : Predicate<X>, Function<X, Y> {

    fun isDefinedAt(x: X): Boolean {
        return test(x)
    }

    override fun apply(x: X): Y {
        return if (isDefinedAt(x)) {
            applyIfDefined(x)
        } else {
            throw IllegalArgumentException("Value: ($x) isn't supported by this function")
        }
    }

    abstract fun applyIfDefined(x: X): Y

    infix fun orElse(fallback: PartialFunction<X, Y>): PartialFunction<X, Y> {
        val outer: PartialFunction<X, Y> = this
        return object : PartialFunction<X, Y>() {
            override fun test(x: X): Boolean {
                return outer.test(x) || fallback.test(x)
            }

            override fun applyIfDefined(x: X): Y {
                return if (outer.isDefinedAt(x)) {
                    outer.applyIfDefined(x)
                } else {
                    fallback.apply(x)
                }
            }

            override fun apply(x: X): Y {
                return applyIfDefined(x)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
espresso profile image
Espresso • Edited

Examples

typealias PartialConsumer<Int> = PartialFunction<Int, Unit>

fun main() {
    val dealNegative = object  : PartialConsumer1<Int>() {
        override fun applyIfDefined(x: Int) {
            println("x-->$x < 0")
        }
        override fun test(t: Int): Boolean {
            return t < 0
        }
    }
    val dealZero = object  : PartialConsumer1<Int>() {
        override fun applyIfDefined(x: Int) {
            println("x-->$x == 0")
        }
        override fun test(t: Int): Boolean {
            return t == 0
        }
    }
    val dealPositive = object  : PartialConsumer1<Int>() {
        override fun applyIfDefined(x: Int) {
            println("x-->$x > 0")
        }
        override fun test(t: Int): Boolean {
            return t > 0
        }
    }

    val dealChain = dealNegative orElse dealZero orElse dealPositive
    dealChain.apply(10)
    dealChain.apply(0)
    dealChain.apply(-10)
}
Enter fullscreen mode Exit fullscreen mode