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.
Makes sense why nobody mentioned it here (given that scala is 99% backend), but kotlin uses it extensively for frontend/UI, the trailing lambda is used in UI DSL like google/jetbrains jetpack compose or compose HTML
@Page
@Composable
fun HomePage() {
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Row(Modifier.align(Alignment.End)) {
var colorMode by ColorMode.currentState
Button(
onClick = { colorMode = colorMode.opposite },
Modifier.borderRadius(50.percent).padding(0.px)
) {
// Includes support for Font Awesome icons
if (colorMode.isLight) FaMoon() else FaSun()
}
}
H1 {
Text("Welcome to Kobweb!")
}
Row(Modifier.flexWrap(FlexWrap.Wrap)) {
SpanText("Create rich, dynamic web apps with ease, leveraging ")
Link("https://kotlinlang.org/", "Kotlin")
SpanText(" and ")
Link("https://github.com/JetBrains/compose-multiplatform/#compose-html", "Compose HTML")
}
}
}