Home > Software design >  app\src\main\kotlin\KotlinApp.kt: (48, 34): Expression 'f[2]' of type 'Any'
app\src\main\kotlin\KotlinApp.kt: (48, 34): Expression 'f[2]' of type 'Any'

Time:09-21

I have been running an algorithm that is designed to take a postfix expression and return the evaluated value.

To carry out the individual functions, I designed an array of lists that basically functions as:

string representation of operation: String, values taken (-1): Integer, function describing what to do: Float I wrote this as

val functions = arrayOf<List<Any>>(
    listOf(" ",1,fun (i:List<Float>):Float = i[0]   i[1]),
    listOf("-",1,fun (i:List<Float>):Float = i[0] - i[1]),
    // etc (rest of them are currently commented out)
)

On compiling this I got the error:

app\src\main\kotlin\KotlinApp.kt: (48, 34): Expression 'f[2]' of type 'Any' cnvoked as a function. The function 'invoke()' is not found

This is referring to how I call f[2](temp:List<Float>) at element f of the array.

I recognise the error here is how as my lists are of type any, the functions inside them aren't assumed to be functions by the compiler. But as I obviously can't cast these to a function, I'm at a loss.

I have tried using lambda expressions instead of anonymous single-expression functions, i.e.

val functions = arrayOf<List<Any>>(
    listOf(" ",1,i : List<Float> -> i[0]   i[1],
    listOf("-",1,i : List<Float> -> i[0] - i[1]),
    // etc 
)

But as I'm not particularly familiar with lambdas, I don't know whether I did it correctly.

Any help would be appreciated

Full KotlinApp.kt file:

package gradleMain;

import org.shuntingyard.sya
import kotlin.math.*
import java.util.Stack


class KotlinApp {

    val functions = arrayOf<List<Any>>(
        listOf(" ",1,fun (i:List<Float>):Float = i[0]   i[1]),
        listOf("-",1,fun (i:List<Float>):Float = i[0] - i[1]),
        // listOf("*",1,{ i : List<Float> -> i[0]*i[1]}),
        // listOf("/",1,{ i : List<Float> -> i[0]/i[1]}),
        // listOf("^",1,{ i : List<Float> -> i[0].pow(i[1])}),
        // listOf("sin",0,{ i : List<Float> -> sin(i[0])}),
        // listOf("cos",0,{ i : List<Float> -> cos(i[0])}),
        // listOf("tan",0,{ i : List<Float> -> tan(i[0])}),
        // listOf("asin",0,{ i : List<Float> -> asin(i[0])}),
        // listOf("acos",0,{ i : List<Float> -> acos(i[0])}),
        // listOf("atan",0,{ i : List<Float> -> atan(i[0])}),
        // listOf("sinh",0,{ i : List<Float> -> sinh(i[0])}),
        // listOf("cosh",0,{ i : List<Float> -> cosh(i[0])}),
        // listOf("tanh",0,{ i : List<Float> -> tanh(i[0])}),
        // listOf("fact",0, /* TODO: Need to incorporate gamma function, once established integrals" */ ),
        // listOf("int",1,/* TODO: Incorporate integrals */),
        // listOf("dif",1,/* TODO: Incorporate differentiation */),
        // listOf("log",0,{ i : List<Float> -> log(i[0], 10F)}),
        // listOf("ln",0,{ i : List<Float> -> ln(i[0])}),
        // listOf("sqrt",0,{ i : List<Float> -> i[0].pow(0.5F)}),
        // listOf("sec",0,{ i : List<Float> -> 1/cos(i[0])}),
        // listOf("csc",0,{ i : List<Float> -> 1/sin(i[0])}),
        // listOf("cot",0,{ i : List<Float> -> 1/tan(i[0])})
    )

    fun calculate(eq:List<String>):Float{ // takes the rpn of the equation and returns the result
        var operand: Stack<String> = Stack()
        var temp = listOf<Float>()

        for(i in eq){
            var n = false
            for(f in functions){
                if(i==f[0]){
                    val x: Int = f[1].toString().toInt()
                    for(j in 0..x){
                        temp =operand.pop().toFloat()
                    }
                    operand.push(f[2](temp))
                    n = true
                    break;
                }
            }
            if(!n){ // when i isnt an operator/function
                operand.push(i)
            }
        }

        val result = operand.peek().toFloat()
        return result
    }
}

fun main(){
    val k = KotlinApp()
    val e = sya(" 3   7 - 2") // runs shunting yard algorithm on equation
    val f = k.calculate(e)
    println("$f")
}

CodePudding user response:

Note: I didnt look at your logic. Helping just to solve your problem of accessing funtion. So here is the thing.

  1. Instead of List of List, you can use Triple object which will help to hold the type of the variable.Since you have only three items in inner list triple might suits you. Because the inner list you are having of multiple types. So you can do typecasting , but it is not recommended.
  2. You can define a function type using TypeAlias for better readability.

Calculate function:

fun calculate(eq:List):Float{ // takes the rpn of the equation and returns the result var operand: Stack = Stack() val temp = mutableListOf()

    for (i in eq){
        var n = false
        for (f in functions){
            if (i == f.first){
                val x: Int = f.second.toString().toInt()
                for(j in 0..x){
                    temp =operand.pop().toFloat()
                }
                operand.push(f.third(temp).toString()) // Float to String
                n = true
                break
            }
        }
        if(!n){ // when i isnt an operator/function
            operand.push(i)
        }
        
    }
    val result = operand.peek().toFloat()
    return result
}

Custom type of the function:

typealias MyFunctionType = (a:List<Float>) -> Float

List of functions:

val functions = arrayListOf<Triple<String,Int,MyFunctionType>>(
    Triple(" ",1,fun (i:List<Float>):Float = i[0]   i[1]),
    Triple("-",1,fun (i:List<Float>):Float = i[0]   i[1])
)
  • Related