If the last argument after default parameters is a lambda, you can pass it either as a named argument or outside the parentheses:
fun foo(
bar: Int = 0,
baz: Int = 1,
qux: () -> Unit,
) { /*...*/ }
foo(1) { println("hello") } // Uses the default value baz = 1
foo(qux = { println("hello") }) // Uses both default values bar = 0 and baz = 1
foo { println("hello") } // Uses both default values bar = 0 and baz = 1
In Scala we do this very explicitly, should scala support this?
IMO there is no benefit. I think Kotlin allows for this because adding multiple parameters lists is not possible and currying requires a lot more boilerplate.
I think Scala already is better in this regard and does not need any changes. Being explicit is barely any longer or inconvenient and a lot easier to understand (in my experience of course).
This is not directly related, but since we’re on the topic of lambdas and Kotlin, one thing I like in Kotlin is this idea of omitting the arguments and the lambda arrow if not needed (e.g., tabulate and fill are the same function). Would that constitute a less confusing alternative to by-name argument?
List(5) { i -> "X".repeat(i + 1) } // tabulate
List(5) { Random.nextInt(1, 11) } // fill
Both expressions use the same function. You just don’t write i -> or _ -> in the second expression because you don’t use the argument. In particular, when there’s no argument, you simply drop the () -> part, making thunks look like by-name argument on the caller side.
In Kotlin it would be a lambda returning Int => A. Braces in Kotlin in expression position always means lambda. This is why adopting that behavior in Scala is not possible.
There is a subtle difference. In Scala { _ + _ } is equivalent to { (a, b) => a + b }; while in Kotlin { it + it } is { a -> a + a }.
And while we are at _ and it, there is one additional benefit of braces marking the lambda boundaries. In Scala, it happened to me that there were cases like a(b(_, _ + c), d(_)) when I needed to stop and think which _ was a parameter to which lambda. In kotlin it is always a parameter to the lambda defined by the nearest enclosing pair of braces which is really intuitive. And also using it in nested lambdas raises a warning.