I am working on a solution for the Temperature Control Problem. It is one of the problems in Kotlin learning fundamentals. So for the thrid argument inside printFinalTemprature function, I am passing a function called conversionFormula but what ever I do, I kept getting the type mismatch error. What am I missing?
fun main() {
var temp : Double = 10.0
fun celsiusToFahrenheit(celsius : Double): Double {
return 9/5 * (celsius) + 32
}
fun kelvinToCelsius(kelvin : Double):Double {
return kelvin - 273.15
}
fun conversionFormula(fahrenheit: Double): Double {
var fiveNine :Double = 0.56
var result :Double = (fiveNine*(fahrenheit - 32.0) + 273.15)
return result
}
printFinalTemperature(temp, "Kelvin", "Celsius", conversionFormula(temp))
}
fun printFinalTemperature(
initialMeasurement: Double,
initialUnit: String,
finalUnit: String,
conversionFormula: (Double) -> Double
) {
val finalMeasurement = String.format("%.2f", conversionFormula(initialMeasurement)) // two decimal places
println("$initialMeasurement degrees $initialUnit is $finalMeasurement degrees $finalUnit.")
}
You just need to switch how you are passing the function. Everything is an expression in Kotlin, and since your printFinalTemperature expects a function as the final argument, you have 2 ways to accomplish this.
The first is to use the function reference with ::. This will only work if the function you are referencing has the same expected signature, so in this case (Double) -> Double. You can try changing one of the Double to Int and you'll see how it breaks.
printFinalTemperature(temp, "Kelvin", "Celsius", ::conversionFormula)
Secondarily, you can pass in a lambda as the final argument, allowing it to "infer" that the function is the correct signature.
printFinalTemperature(temp, "Kelvin", "Celsius") {
conversionFormula(it)
}
In this case, the it comes from the lambda as the default argument name. You could give it an explicit name such as:
printFinalTemperature(temp, "Kelvin", "Celsius") { newTemp ->
conversionFormula(newtemp)
}
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")
}
Note: I didnt look at your logic. Helping just to solve your problem of accessing function.
So here is the thing.
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.
You can define a function type using TypeAlias for better readability.
Calculate function:
fun calculate(eq:List<String>):Float{ // takes the rpn of the equation and returns the result
var operand: Stack<String> = Stack()
val temp = mutableListOf<Float>()
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])
)
I have a function in Kotlin which takes a particular string as input. Depending on the input, I want to create a variable of a specific type and do some computations on it.
For example,
fun compute(input: String): Any{
if(input=="2d"){
var point: Point2D;// Points2D - x: int, y: int
//initilize and do some computations
return point.findDistanceFromOrigin()
}else if(input=="2d-1"){
var point: Point2DWithP1AsOrigin;// Point2DWithP1AsOrigin - x: int, y: int
//initilize and do some computations
return point.findDistanceFromOrigin()
}else if(input=="2d-2"){
var point: Point2DWithP2AsOrigin;
//initilize and do some computations
return point.findDistanceFromOrigin()
}
.
.
.
}
You can see in the above example, I want to initilize the type of point depending on the input and do computation and return.
All the if-else conditions have the same code except for the definition of the variable. How can I put all this in a single block with something like this:
var point: if(input=="2d) Point2D::class else if(input=="2d-1") Point2DWithP1AsOrigin::class.....
How can I do that?
You could do something like this
fun compute(input: String): Any{
val point: MyPoint = when(input) {
"2d" -> Point2D()
"2d-1" -> Point2DWithP1AsOrigin()
"2d-2" -> Point2DWithP2AsOrigin()
else -> Point2D() //fallback is necessary
}
//initilize and do some computations
return point.findDistanceFromOrigin()
}
But then it's essential that all those classes share the same interface. Because they need to have the same methods in order to do the same operations on them.
For example like this:
class Point2D : MyPoint {
override fun findDistanceFromOrigin() = 5
}
class Point2DWithP1AsOrigin : MyPoint{
override fun findDistanceFromOrigin() = 6
}
class Point2DWithP2AsOrigin : MyPoint{
override fun findDistanceFromOrigin() = 7
}
interface MyPoint {
fun findDistanceFromOrigin() : Int
}
You can store constructor references and then invoke required one
fun main() {
val constructors = mapOf(
"2d" to ::Point2D,
"2d-1" to ::Point2DWithP1AsOrigin,
"2d-2" to ::Point2DWithP2AsOrigin,
)
val type = "2d-2"
val constructor = constructors[type] ?: throw IllegalArgumentException("$type not supported")
val point = constructor()
println(point::class)
}
Output
class Point2DWithP2AsOrigin
I'm new to Kotlin and try to convert a project from Java to Kotlin
I just need one last step and I don't understand what's going on :(
I'm getting a Not enough information to infer type variable T on model.predict call
override fun link(word: String): LinkSuggestion {
val input: DoubleArray = gramToInt.toArray(word)
val output: Array<Any> = model.predict(input)
// ~~~~~~~ Not enough information to infer type variable T
val maxPredictionIndex: Int = (output[output.size - 1] as Long).toInt()
val maxPredictionProbability: Double = output[maxPredictionIndex] as Double
return LinkSuggestion(word, intToLink.fromInt(maxPredictionIndex), maxPredictionProbability)
}
where model is import org.pmml4s.model.Model
The previous Java code:
#Override
public LinkSuggestion link(String word) {
double[] input = gramToInt.toArray(word);
Object[] output = model.predict(input);
int maxPredictionIndex = ((Long) output[output.length - 1]).intValue();
double maxPredictionProbability = (Double) output[maxPredictionIndex];
return new LinkSuggestion(word, intToLink.fromInt(maxPredictionIndex), maxPredictionProbability);
}
I needed to write
val output: Array<Any> = model.predict<Any>(input)
I have an array of classes with values. E.g.
class MyData(val value: Double)
class MyClass(val values: List<MyData>)
it's pretty easy to get the sum of all values in the array:
values.sumByDouble { it.value }
Is there an equivalent to multiply these values inside those classes?
You can create an extension function:
public inline fun <T> Iterable<T>.multiplyByDouble(selector: (T) -> Double): Double {
this.firstOrNull() ?: return 0.0
var result = 1.0
for (element in this) {
result *= selector(element)
}
return result
}
and use it:
listOf(2.0, 3.0).multiplyByDouble { it } // 6.0
listOf<Double>().multiplyByDouble { it } // 0.0
There is no dedicated function for that, but you can use reduce for that. But there is a problem. Since the element (in this case of type T with S as upper bound) has to be a subtype of the accumulator (in this case of type S),
inline fun <S, T : S> Iterable<T>.reduce(
operation: (acc: S, T) -> S
): S
which is not the case in your example, it would be a good idea to first map the MyData elements to the Double value:
val l = listOf(MyData(1.0), MyData(2.0), MyData(3.0))
.map { it.value }
.reduce { acc, ele -> acc * ele }
println(l) // 6.0
Alternatively, you could change your data model (like shown here) but that might not be a good idea just for the sake of multiplying all values, but it depends on your use-case.