Лямбды назначены переменным в Котлин.Зачем? - PullRequest
0 голосов
/ 17 октября 2018

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

fun double ( i: Int ) = i*2

и если я определяю переменную и назначаю ей лямбду (с идентичным телом):

var double = { i : Int -> i*2 }

Я получу тот же результат, если позвоню double(a) с любой декларацией.Это оставляет меня в замешательстве.Когда это необходимо, рекомендуется, выгодно определять переменную как лямбду, а не определять функцию для нее?

Ответы [ 4 ]

0 голосов
/ 17 октября 2018

Если вы передадите лямбду в качестве параметра функции, она будет сохранена в переменной.Вызывающему приложению может потребоваться сохранить это (например, прослушиватель событий для последующего использования).Поэтому вы должны иметь возможность хранить его как переменную.Однако, как сказано в ответе, вы должны делать это только тогда, когда это необходимо!

0 голосов
/ 17 октября 2018

Во-первых, если я вас правильно понимаю, ваш вопрос звучит так: «Почему в Котлине есть функции первоклассных граждан - И когда их использовать как таковые?», Верно?

Функции Kotlin являются первоклассными, что означает, что они могут храниться в переменных и структурах данных, передаваться в качестве аргументов и возвращаться из других функций более высокого порядка.Вы можете работать с функциями любым способом, который возможен для других не функциональных значений.( см. Здесь )


Как указано в документации, одним из вариантов использования являются функции высшего порядка .В качестве первого шага я оставлю здесь ссылку на википедию: https://en.wikipedia.org/wiki/Higher-order_function

По сути, функция высшего порядка - это функция, которая принимает функции в качестве параметров или возвращает функцию .Это означает, что функция высшего порядка имеет по крайней мере один параметр типа функции или возвращает значение типа функции .

Следуя короткому примеруфункция высшего порядка, которая получает параметр типа функции (Int) -> Boolean:

fun foo(pred: (Int) -> Boolean) : String = if(pred(x)) "SUCCESS" else "FAIL"

Эта функция высшего порядка теперь может вызываться с любой функцией (Int) -> Boolean.


В документах также указывается ... [может использоваться] любым способом, который возможен для других не функциональных значений .

Это означает, что вы можете, например, назначать различные функциипеременная, в зависимости от вашего текущего контекста.

Например:

// This example is verbose on purpose ;)
var checker: (Int) -> Boolean
if (POSITIVE_CHECK) {
    checker = { x -> x > 0 } // Either store this function ...
} else {
    checker = { x -> x < 0 } // ... or this one ...
}
if (checker(someNumber)) { // ... and use whatever function is now stored in variable "checker" here
  print("Check was fine")
}

(код не проверен)

0 голосов
/ 17 октября 2018

Когда это необходимо, рекомендуется, выгодно определять переменную как лямбду, а не определять для нее функцию?

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

В JVM fun значительно легче, как с точки зрения оперативной памяти, так и с точки зрения накладных расходов.Он компилируется в метод Java, тогда как val компилируется в поле экземпляра + getter + синтетический класс, который реализует функциональный интерфейс + одноэлементный экземпляр этого класса, который вы должны извлечь, разыменовать и вызвать метод для него.

Вы должны рассматривать тип функций val или var только тогда, когда что-то заставляет вас это делать.Одним из примеров является то, что вы можете динамически заменить var и эффективно изменить определение функции.Вы также можете получать функциональные объекты извне, или вам может понадобиться API, которому они нужны.

В любом случае, если вы когда-либо будете использовать свойство класса с типом функции, вы будете знать,почему ты это делаешь.

0 голосов
/ 17 октября 2018

Вы можете определить переменную и назначить ее лямбда, если вы хотите изменить поведение по некоторым причинамНапример, у вас есть разные формулы для нескольких случаев.

val formula: (Int) -> Int = when(value) {
    CONDITION1 -> { it*2 }
    CONDITION2 -> { it*3 }
    else -> { it }
}
val x: Int = TODO() 
val result = formula(x)

Если вам просто нужна вспомогательная функция, вы должны определить ее как fun.

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