Оценить блок кода в Kotlin (чтобы скрыть переменные внутри области видимости)

#kotlin

#kotlin

Вопрос:

В Scala вы можете написать

 val x = {
  ... do some complex computations ..
  42
}
  

чтобы скрыть материал внутри блока кода.

Самое близкое, что я нашел в Kotlin, это:

 val x = {
  ... do some complex computations ..
  42
}()
  

Есть ли лучший способ?

Редактировать:

  • разве run {} в приведенном выше примере не то же самое
  • является ли вызов run дорогостоящим?

ОТВЕТ:

  • используя run {} встроенные строки, тогда как {}() ЭТОГО НЕ делает (см. Мой собственный ответ ниже)

Комментарии:

1. «не выполняется {} в приведенном выше примере, по сути, то же самое»: это даст тот же результат, но вызов run гарантированно будет встроенным, при выполнении { ... }() будет создан объект функции и вызван он.

2. @marstran почему создается объект функции? Run также просто вызывает () при передаче лямбда

3. Потому что run это встроенная функция. Тело лямбды копируется компилятором на сайт вызова.

Ответ №1:

Используйте run функцию. Он принимает функцию в качестве параметра, запускает ее и возвращает результат.

 val x = run {
  ... do some complex computations ..
  42
}
  

run Функция встроена, поэтому у нее не будет накладных расходов на производительность.

Ответ №2:

Да, есть функция run.

 val x = run {
    ...
    42
}
  

Ответ №3:

А также вы также можете использовать эти методы:

  val a=1.also{
    // your code
}
val b=2.apply{
    // your code}
}
val c=3.let{
    // your code
}
val d=4.runCatching{
    // your code
}
  

Ответ №4:

Чтобы проверить встраивание при использовании run , я создал небольшой пример:

     fun main() {
        {
            Math.random()
        }()

        run {
            Math.random()
        }
    }
  

и просмотрел созданный байт-код:

   public final static main()V
   L0
    LINENUMBER 2 L0
    GETSTATIC TestKt$main$1.INSTANCE : LTestKt$main$1;
    CHECKCAST kotlin/jvm/functions/Function0
    INVOKEINTERFACE kotlin/jvm/functions/Function0.invoke ()Ljava/lang/Object; (itf)
    POP
   L1
    LINENUMBER 6 L1
   L2
   L3
   L4
    ICONST_0
    ISTORE 0
   L5
    LINENUMBER 7 L5
    INVOKESTATIC java/lang/Math.random ()D
   L6
   L7
    LINENUMBER 6 L7
   L8
    POP2
   L9
    LINENUMBER 9 L9
    RETURN
   L10
    LOCALVARIABLE $i$a$-run-TestKt$main$2 I L5 L7 0
    MAXSTACK = 2
    MAXLOCALS = 1

  

Итак, действительно:

  • Вызов через () вызывает сгенерированный Function0 производный класс, который инкапсулирует блок в виде лямбда (метки L0 )
  • Вызов через run полностью вставляет блок (метку L5 )