https://kotlinlang.org logo
#announcements
Title
# announcements
h

Hullaballoonatic

12/04/2019, 5:11 PM
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

Mike

12/04/2019, 5:17 PM
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

Edgars

12/04/2019, 5:19 PM
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

Hullaballoonatic

12/04/2019, 5:20 PM
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

streetsofboston

12/04/2019, 5:36 PM
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

karelpeeters

12/04/2019, 5:44 PM
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

Hullaballoonatic

12/04/2019, 6:07 PM
whoa, I didn't know that
That's essentially SAM delegation, right? I actually don't understand what the additional nesting is doing
k

karelpeeters

12/04/2019, 6:10 PM
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

Hullaballoonatic

12/04/2019, 6:11 PM
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

karelpeeters

12/04/2019, 6:12 PM
Well lambdas are just values like everything else, and they implement the
(T) -> R
interface.
h

Hullaballoonatic

12/04/2019, 6:15 PM
everything's a 1 or 0 somewhere in memory when it's all said and done
k

karelpeeters

12/04/2019, 6:16 PM
Copy code
val lambda = { x: Int -> 2 * x }
println(lambda is (Int) -> Int)
2 Views