2016-08-15 3 views
3

я думаю, что этот вопрос несколько связан с Kotlin function declaration: equals sign before curly bracesКотлин: Фигурные скобки вокруг нескольких выражений (или заявления)

В Scala, каждое высказывание является выражением (возможно, с Unit типа). Если мы окружаем несколько выражений фигурными скобками, то окончательное выражение представляет собой фактическое значение фигурной скобки. Таким образом,

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

Тип a является Int и код выводит значение 4.

Однако в Котлине это несколько другое. Если мы делаем то же самое в Котлин,

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

Тип a является () -> Int и код печатает Function0<java.lang.Integer>, что означает 0-кратную функциональный объект с результатом типа Int.

Так что, если мы хотим напечатать значение 4, нам нужно сделать println(a()).

Фактически, выражение {} в Котлине является функцией () ->().

Я не могу найти объяснения об этом на официальных страницах справочника Kotlin. Без списка параметров или -> фигурные скобки выполняют функцию?

Когда я использую Scala, я пишу много кодов, таких как первый код. Однако в Kotlin он создает объект функции, и мы должны вызывать функцию, которая может быть накладными расходами в цикле или рекурсии.

  1. Есть ли какой-либо документ об этой вещи: только фигурные скобки сделать функциональный объект?

  2. Любой способ обхода накладных расходов во втором коде, если он используется много раз?

EDIT

Вот фактический код, который перебирает много раз:

в Java

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

в Scala

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

в Котлин

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

Вы можете видеть, только Котлин делает много функциональных объектов и называет их.

+0

Параметр 'while' код не будет идиоматическим для чтения. Разве не лучше использовать (буферизованные) потоки для этого? – voddan

ответ

10

В Котлин {} всегда лямбда-выражение или часть конструкции синтаксиса, например while(true) {}. Вероятно, отличается от Scala, но легко понять, тем не менее.

То, что вы, вероятно, хотите есть:

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

Котлин не встраиваемая в понятие «кодовых блоков в любом месте». Вместо этого мы используем стандартные функции-помощники, такие как run в приведенном выше примере.

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

+4

Обратите внимание, что в отличие от других решений, этот не генерирует никаких анонимных классов и, следовательно, более эффективен. –

5

Если {} определяет функцию, вы можете просто вызвать функцию при объявлении его, которая сразу же оценить его:

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

печатает 4. (Обратите внимание на () в конце блока)

3

В Scala, каждое высказывание является выражением (возможно, с типом Unit)

Это не совсем верно. Проверить: Is everything a function or expression or object in scala?

Как Золтан сказал {} определяет функции, так вместо:

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

должно быть:

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

или

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

Если вы хотите напечатать значение, а не функция, вы можете попытаться объявить переменную д затем использовать одну из функций Котлин, чтобы изменить значение, как в примере ниже:

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

чтения: Higher-Order Functions and Lambdas

Надежда это поможет

Смежные вопросы