Home > Net >  I want to create new type of simple operator class kotlin
I want to create new type of simple operator class kotlin

Time:05-19

What I want to do is save operator with number in list and evaluate it after pushing it to list

need 2 types of operator Add and Multiply

Plus(x) (x is number)
Multiply(x) (x is number)
lis = [ Plus(3), Multiply(3), Plus(4), Multiply(2) ]

When Plus Start
lis.fold(0) { total, operator -> blar..blar }
-> (((0   3) * 3)   4) * 2

When Multiply Start
lis.fold(1) { total, operator -> blar..blar }

how to declare abstract operator

I think Plus and Multiply Operator has one infix function something like below

infix fun <T>evaluate(value: T): T = this value
or
infix fun <T>evaluate(value: T): T = this*value

CodePudding user response:

In order to allow the distinction whether to use a 0 or a 1 depending on the first element, you could define your operation with an identity element:

open class Operation(
    val op: (Double) -> Double,
    val identity: Double,
)

class Plus(operand: Double) : Operation({ it   operand }, 0.0)
class Multiply(operand: Double) : Operation({ it * operand }, 1.0)

Then, the application of all elements in a list can be defined as:

fun List<Operation>.apply(): Double = if (isEmpty()) 1.0 else
    fold(first().identity) { total, operation -> operation.op(total) }

The application of all elements as in your example can then be invoked using apply:

val lis = listOf(Plus(3.0), Multiply(3.0), Plus(4.0), Multiply(2.0))
lis.apply()

If you do not like that an operator is defined and applied via its property op (e.g. the application of Plus(3.0) to a value 5.0 is done by Plus(3.0).op(5.0)), we can alternatively define Operation and the concrete subclasses in the following way:

abstract class Operation(val identity: Double) {
    abstract operator fun invoke(x: Double): Double
}

class Plus(private val operand: Double) : Operation(0.0) {
    override fun invoke(x: Double): Double = x   operand
}

class Multiply(private val operand: Double) : Operation(1.0) {
    override fun invoke(x: Double): Double = x * operand
}

Then, the apply function would also change:

fun List<Operation>.apply(): Double = if (isEmpty()) 1.0 else
    fold(first().identity) { total, operation -> operation(total) }

which might look a bit more intuitive.

The invoke operator allows us to apply the Operation like a function to a value, e.g. you can also write Plus(3.0)(5.0) to apply _ 3.0 to the value 5.0.

  • Related