Kotlin: Curly braces around several expressions (or statements)
Asked Answered
B

3

10

I think this question is somewhat related to Kotlin function declaration: equals sign before curly braces

In Scala, every statement is an expression (possibly with Unit type). If we surround multiple expressions with braces, then the final expression is the actual value of the curly braced part. Therefore,

// Scala
val a = {
  val b = 1
  val c = b + b
  c + c
}
println(a)

The type of a is Int and the code prints the value 4.

However, in Kotlin, this is somewhat different. If we do the same thing in the Kotlin,

// Kotlin
val a = {
  val b = 1
  val c = b + b
  c + c
}
println(a)

The type of a is () -> Int and the code prints the Function0<java.lang.Integer>, which means a 0-ary function object with result type Int.

So if we want to print the value 4, we need to do println(a()).

In fact, the expression {} in Kotlin is a function () -> ().

I cannot find an explanation about this in Kotlin official reference pages. Without a parameter list or ->, curly braces make a function?

When I use Scala, I write many codes like the first code. However, in Kotlin, it creates a function object and we have to call the function, which may be an overhead in a loop or recursion.

  1. Is there any document about this thing: just curly braces make a function object?

  2. Any way to workaround the overhead in the second code if it is used many times?

EDIT

Here is the actual code that iterates many times:

in Java

while ((count = input.read(data, 0, BYTE_BLOCK_SIZE)) != -1) {
    ....
}

in Scala

while {
  count = input.read(data, 0, BYTE_BLOCK_SIZE)
  count != -1
} {
  ....
}

in Kotlin

while ({
    count = input.read(data, 0, BYTE_BLOCK_SIZE)
    count != -1
}()) {
    ...
}

You can see, only Kotlin makes a lot of function objects and calls them.

Beastings answered 15/8, 2016 at 9:9 Comment(1)
The while code does not seem to be idiomatic for reading. Wouldn't it better to use (buffered) streams for that?Tegument
T
19

In Kotlin {} are always a lambda expression or a part of a syntax construct like while(true) {}. Probably different from Scala, but easy to grasp, nonetheless.

What you probably want is:

val a = run {
  val b = 1
  val c = b + b
  c + c
}
println(a)

Kotlin has no build-in concept of "code blocks anywhere". Instead we use standard functions-helpers like run in the example above.

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/run.html

Tegument answered 15/8, 2016 at 10:34 Comment(1)
Note that unlike the other solutions, this one doesn't generate any anonymous classes and is therefore more efficient.Fairway
A
7

If {} defines a function, you can just call the function upon declaring it, which will immediately evaluate it:

val a = {
  val b = 1
  val c = b + b
  c + c
}()
println(a)

prints 4. (Note the () at the end of the block)

Albemarle answered 15/8, 2016 at 9:15 Comment(0)
M
3

In Scala, every statement is an expression (possibly with Unit type)

That's not exactly true. Check: Is everything a function or expression or object in scala?

As Zoltan said {} defines functions so instead of:

// Kotlin
val a = {
  val b = 1
  val c = b + b
  c + c
}
println(a)

it should be:

// Kotlin
val a = {
  val b = 1
  val c = b + b
  c + c
}
println(a()) //you defined a function, which returns `4`, not expression

or

// Kotlin
val a = {
  val b = 1
  val c = b + b
  c + c
}() //note these braces
println(a)

If you would like to print a value, not function, you can try to declare the variable and then use one of Kotlin functions to change a value like in example below:

var sum = 0
ints.filter { it > 0 }.forEach {
  sum += it
}
print(sum)

Read: Higher-Order Functions and Lambdas

Hope it will help

Merna answered 15/8, 2016 at 9:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.