Can one override a function with lambda expression?

Can one override a function with lambda expression?
I was following the koans Kotlin Playground: Edit, Run, Share Kotlin Code Online,
and below code

import java.util.*

fun getList(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, object : Comparator<Int> {
        override fun compare = {x: Int, y: Int -> y - x}
    })
    return arrayList
}

gave me error messages:

Object is not abstract and does not implement abstract member public abstract fun compare(p0: Int!, p1: Int!): Int defined in java.util.Comparator
'compare' overrides nothing
Expecting '('

Can someone elaborate these messages?

EDIT:
additionally when I tried different codes in the line starting with override fun compare ,
1.

        override fun compare(x: Int, y: Int) {
            return y - x
        }

this did not work as well, producing error messages

Return type of 'compare' is not a subtype of the return type of the overridden member 'public abstract fun compare(p0: Int!, p1: Int!): Int defined in java.util.Comparator'
Type mismatch: inferred type is Int but Unit was expected

I don’t understand the error message. Why was the expected type Unit, not Int? Shouldn’t the compiler expect the return type as Int?
BUT
2. with a slight modification,

        override fun compare(x: Int, y: Int): Int {
            return y - x
        }

this worked.
3.

        override fun compare(x: Int, y: Int) = y - x

This works also. But in this case, I also didn’t explicitly write the return type, same as approach 1.
What are the differences between them? Why did 1. produce error while the other two didn’t? What’s happening under the hood?

EDIT 2:
I looked at the next koan Kotlin Playground: Edit, Run, Share Kotlin Code Online,
here indeed the lambda expression was used, but not with the object expression.

import java.util.*

fun getList(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, { x, y -> y - x })
    return arrayList
}

But then here, inside the lambda expression the types are not explicitly stated. Why would this work, compared to the other approaches above?

Let’s look at the first 3 functions you used with the object expression.

override fun compare = {x: Int, y: Int -> y - x}  // 1
override fun compare(x: Int, y: Int) { return y -x } // 2
override fun compare(x: Int, y: Int) { return y - x }: Int // 3
override fun compare(x: Int, y: Int) = y - x  // 4

You already worked out that 1 and 2 are invalid.
I think the easiest way to explain your problem is by looking at how functions are declared in kotlin.
A function always needs a few things.

So the problem with function 1 is that it’s missing a parameter list and also tries to mix a single expression body with a normal expression body. Also it seems like you try to return a lambda instead of executing the code within the braces.
The problem with function 2 is that you forgot to specify the return type. This means the default of Unit is used. So the override fails, because you have the wrong return type. Also the return statement will not compile since it returns Int but the function returns Unit.
Function 3 and 4 are correct. Function 3 has the right parameter list, returns Int and also has a valid function body. Function 4 uses a single expression body and the compiler therefor is able to infere the correct retrun type.

You should read the documentation about functions again.

I think you meant to put an :Int return type here?

Yes, the error message can be confusing. You can also read it as: the expected type was Int but Unit was found.

In fact both types are infered, hence strictly speakint it would need to read “the inferred types do not match: Int, Unit”

This doesn’t change anything in the fact, that there is an error. I agree that the error message can be confusing, and sometimes read as if it got the direction wrong.

Yes thx. Changed it above :wink:

Thank you for the kind reply. I also got some help in the slack channel, and it helped me clarify. I’ll summarize here for the sake of completeness.

  • Functions in Kotlin have no type inference for parameters - all parameters types have to be specified explicitly.
  • One needs to explicitly provide return type for a function with body enclosed in { } , otherwise compiler assumes the function returns Unit. Return type inference works only for single-expression functions.
  • For lambdas the compiler can infer types of their parameters from the context.

And the answer to the original question in the title: “Can one override a function with lambda expression?”:

  • No. I was confusing two different things.