where in the language might you ever see curly bra...
# announcements
h
where in the language might you ever see curly braces sequentially like this:
Copy code
{ ... } { ... }
I'm musing on the reason why you can't place multiple lambda arguments outside the function parameter parentheses:
Copy code
myPairs.associateBy { (k, _) -> k } { (_, v) -> v } // does not compile
myPairs.associateBy({ (k, _) -> k }, { (_, v) -> v }) // compiles
nbd. just thinking of course maybe it just doesn't read well, since parameters are separated by a comma, and sequential lambda arguments outside the parentheses would not.
m
I don't think it appears anywhere in the language, but I suspect it would be difficult to read, and especially if either of the lambdas were multi-line. We're used to seeing
,
and
(
for combining things, and
{}
outside
()
for last is as much about DSL writing as anything else.
e
I don't think it's possible, unless I'm missing something.
Copy code
fun a(block: () -> Boolean): (() -> Boolean) -> Boolean = { block() }

fun test() {
    a { true } { true } // Only one lambda expression is allowed outside a parenthesized argument list
    a { true }.invoke { true } // OK
}
h
we're definitely on the same page, then. i even think putting a lambda argument outside the function params hurts readability when it isn't the only argument.
foo(a, b, c) { it.bar() }
implies
{ it.bar() }
happens after
foo
returns.
@Edgars there's the germane example. thanks. now i wonder why kotlin doesn't allow
a { true }  { true }
s
Even without any argument, eg
foo {  … lambda … }
, foo may not return before ‘lambda’ is executed. If it is synchronous, ‘lambda’ is executed while foo is executing. If it is asynchronous, ‘lambda’ may get executed at any time or never.
k
Copy code
class Foo: (Int) -> Int by { x: Int -> 2 * x } {
    fun foo() = println("foo")
}
And you can even keep nesting them:
Copy code
class Foo : (Int) -> Int by object : (Int) -> Int by object : (Int) -> Int by { 
    2 * it
} {
    fun obj1() = println("obj")
} {
    fun obj2() = println("obj")
} {
    fun foo() = println("foo")
}
h
whoa, I didn't know that
That's essentially SAM delegation, right? I actually don't understand what the additional nesting is doing
k
Hmm I don't know if you should call this SAM because
(T) -> R
is actually an interface and
{ it * 2}
is just a value that happens to implement that interface.
Secondly, the expression
object: (Int) -> Int by x
just returns a value that also happens to implement that interface.
And
by x
expects a value that implements the interface.
h
I'm just surprised you can delegate to an interface by a lambda. the only think that makes sense is if that interface has only a single function
k
Well lambdas are just values like everything else, and they implement the
(T) -> R
interface.
h
everything's a 1 or 0 somewhere in memory when it's all said and done
k
Copy code
val lambda = { x: Int -> 2 * x }
println(lambda is (Int) -> Int)