Различия между нормальной функцией и функцией выражения - PullRequest
0 голосов
/ 28 мая 2018

Мы уже знаем, что все функции в Kotlin являются типами, поэтому, если есть эта функция:

    fun p() : Unit 
{
    println("Hello P")
}

Это просто функция, которая не имеет параметров и возвращает единицу, поэтому я могу объявить другую функцию, которая выполняетто же самое

fun y() : () -> Unit = 
{
    println("Hello Y")

}

Но при запуске этих функций получаются разные результаты

p() //-->  will print out "Hello P"

y() //--> doesn't print out anything

Но если я вызываю y () так:

y()() //--> will print out "Hello Y"

Не могли бы вы помочь мне понять это.

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

Тип возврата вашего примера

fun y() : () -> Unit = 
{
    println("Hello Y")

}

на самом деле является типом функции ()->Unit, поэтому при его вызове эта анонимная функция возвращается без ее вызова.Вы можете назвать это так:

y()()

Вместо этого вы можете создать переменную, содержащую эту функцию :

val y = { println("Hello Y") }

И просто вызвать ее так: y()

0 голосов
/ 29 мая 2018

Мы можем немного переписать определения p и y, не меняя их значения:

fun p() {
    println( "Hello p")
}

fun y() = {
    println( "Hello y")
}

Обратите внимание, что синтаксис почти идентичен (= делает все различия), что являетсянемного неудачно, поскольку p и y - совершенно разные звери.

  • fun p - это объявление функции.p не принимает параметры и возвращает Единицу
  • fun y - объявление функции.y не принимает параметров и возвращает функцию с типом () -> Unit

Поскольку вызов y() возвращает функцию, вам необходимо вызвать эта функция для печати: y()()

Все вышеперечисленное мало говорит о типе p и y, - только то, что они возвращают определенные типы:

  • фактический тип p равен KFunction0< Unit >
  • фактический тип y равен KFunction0< () -> Unit >

Если вы хотите поиграть с этим немного больше :-) рассмотрите:

fun yy() = {
    ::p
}

Вы можете проверить, что yy()()() печатает hello p и его тип KFunction0<()->KFunction0<Unit>>

0 голосов
/ 28 мая 2018

Мы уже знаем, что все функции в Kotlin являются типами

Это не так.Существуют типы функций, экземпляры типов функций и объявления функций.Это объявление функции, тип возвращаемого значения которой Unit:

fun p() : Unit 
{
    println("Hello P")
}

Это тип функции:

() -> Unit

Это объявление функции, тип возвращаемого значения которойтип функции () -> Unit:

fun y() : () -> Unit = 
{
    println("Hello Y")
}

В то время как при вызове p() выполняется оператор print, при этом y() просто возвращает экземпляр функции, который при вызове выполнит оператор print:

y()()

Структурно, объявление функции очень похоже на объявление свойства с типом функции:

val x: () -> Unit = 
{
    println("Hello X")
}

Синтаксически вы можете использовать его так же:

x()

Вы также можете передать его другой функции:

fun higherOrderFun(block: () -> Unit) [
    println("higher order")
    block()
}

higherOrderFun(x)

Но вы не можете сделать то же самое с объявлением функции:

higherOrderFun(p) // Compiler error

Это потому, что объявление функции не«вещь», которую вы можете передать, это просто объявление исполняемого кода.

Вы также можете создать экземпляр типа функции из объявления функции:

::p

Теперь это эквивалентнодо x.На самом деле, вы также можете написать

val x = ::p

, и теперь у вас есть экземпляр x, который ничего не делает, но немедленно вызывает p() и возвращает его значение.

Пока есть сильныйформальная симметрия между объявлениями функций и экземплярами функций, и есть даже языки, которые имеют только последние (например, JavaScript или LISP), первые лучше для производительности и использования памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...