Permalink
Browse files

Merge pull request #51 from diziaq/master

Update lambdas.md
  • Loading branch information...
phplego committed Nov 2, 2017
2 parents 65d5c3d + 54ad895 commit 7590b79a17545a9a1686129ff7f741ca98727297
Showing with 50 additions and 38 deletions.
  1. +50 −38 lambdas.md
View
@@ -8,9 +8,8 @@ url: https://kotlinlang.ru/docs/reference/lambdas.html
# Высокоуровневые функции и лямбды
## Функции высшего порядка
Высокоуровневая функция - это функция, которая принимает другую функцию в качестве входного аргумента,
либо имеет функцию в качестве возвращаемого результата. Хорошим примером такой функции является `lock()`,
которая берёт залоченный объект и функцию, применяет лок, выполняет функцию и отпускает `lock`:
Функция высшего порядка - это функция, которая принимает функции как параметры, или возвращает функцию в качестве результата.
Хорошим примером такой функции является `lock()`, которая берёт блокирующий объект и функцию, получает блокировку, выполняет функцию и отпускает блокировку:
``` kotlin
fun <T> lock(lock: Lock, body: () -> T): T{
@@ -24,38 +23,38 @@ fun <T> lock(lock: Lock, body: () -> T): T{
}
```
Давайте проанализируем этот блок. Параметр `body` имеет функциональный тип: `() -> T`, то есть предполагается,
что это функция, которая не имеет никаких входных аргументов и возвращает значение типа `T`. Она вызывается
внутри блока `try`, защищена `lock`, и её результат возвращается функцией `lock()`.
Проанализируем этот код: `body` имеет функциональный тип: `() -> T`, то есть параметр должен быть
функцией без параметров, возвращающей значение типа `T`. Она вызывается
внутри блока `try`, под защитой объекта `lock`, получившего блокировку вызовом функции `lock()`.
Если мы хотим вызвать метод lock(), мы можем подать другую функцию в качестве входящего аргумента
(более подробно читайте [Ссылки на функции](reflection.html#function-references)):
Если мы хотим вызвать метод `lock()`, можно передать другую функцию в качестве входящего аргумента
(подробно читайте [Ссылки на функции](reflection.html#function-references)):
``` kotlin
fun toBeSynchronized() = sharedResource.operation()
val result = lock (lock, ::toBeSynchronized)
```
Другой, наиболее удобный способ применения [лямбда-выражения](lambdas.html#lambda-expressions-and-anonymous-functions):
Обычно удобней передавать [лямбда-выражения](lambdas.html#lambda-expressions-and-anonymous-functions):
```kotlin
val result = lock(lock, { sharedResource.operation() })
```
Лямбда-выражения более подробно описаны [здесь](lambdas.html#lambda-expressions-and-anonymous-functions), но в целях продолжить этот раздел, давайте произведём краткий обзор:
- Лямбда-выражения всегда заключены в фигурные скобки,
- Параметры этого выражения (если такие есть) объявлены до знака `->` (параметры могут быть опущены),
- Тело выражения идёт после знака `->`.
Лямбда-выражения подробно описаны [здесь](lambdas.html#lambda-expressions-and-anonymous-functions), но ради продолжения этого раздела сделаем краткий обзор:
- Лямбда-выражение всегда заключено в фигурные скобки;
- Его параметры (если они есть) объявлены до знака `->` (допустимо не указывать параметры);
- Тело выражения следует после знака `->`.
В Kotlin существует конвенция, по которой, если последний параметр функции является функцией, и вы применяете лямбда-
выражение в качестве аргумента, вы можете указать её вне скобок:
В Kotlin есть конвенция, согласно которой, если последний параметр функции является функцией,
которая передается в виде лямбда-выражения, можно вынести его за скобки:
``` kotlin
lock (lock) {
sharedResource.operation()
}
```
Другим примером функции высшего порядка служит функция `map()`:
Следующим примером функции высшего порядка выберем функцию `map()`:
``` kotlin
fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
val result = arrayListOf<R>()
@@ -65,56 +64,70 @@ fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
}
```
Эта функция может быть вызвана следующим образом:
Эту функцию можно вызвать так:
``` kotlin
val doubled = ints.map { it -> it * 2 }
```
Обратите внимание, что параметры могут быть проигнорированы при вызове функции в том случае, если лямбда является единственным аргументом
для её вызова.
Обратите внимание, что скобки можно вообще не указывать при вызове функции,
если лямбда является единственным аргументом.
<!--it: implicit name of a single parameter-->
<!--http://kotlinlang.org/docs/reference/lambdas.html#it-implicit-name-of-a-single-parameter-->
## Ключевое слово `it`: неявное имя единственного параметра
Ещё одной полезной особенностью синтаксиса является возможность опустить объявление параметра функции в случае, если он
единственный (вместе с `->`). Слово `it` будет принято в качестве имени для такой функции:
Ещё одна полезная конвенция состоит в том, что если функциональный литерал имеет ровно один параметр,
его объявление можно удалить (вместе с `->`), и обращаться к нему по имени `it`:
``` kotlin
ints.map { it * 2 }
```
Это соглашение позволяет писать код в [LINQ](http://msdn.microsoft.com/en-us/library/bb308959.aspx) стиле:
Эти конвенции позволяют писать код в стиле [LINQ](http://msdn.microsoft.com/en-us/library/bb308959.aspx):
``` kotlin
strings.filter { it.lenght == 5 }.sortBy { it }.map { it.toUpperCase() }
```
### Символ подчеркивания для неиспользуемых переменных (since 1.1)
Если параметр лямбды не используется, разрешено применять подчеркивание место его имени
``` kotlin
map.forEach { _, value -> println("$value!") }
```
### Деструктуризация в лямбдах (since 1.1)
Деструктуризация в лямбдах описана в [деструктурирующие объявления](multi-declarations.html#destructuring-in-lambdas-since-11).
## Инлайн функции
Иногда необходимо улучшить производительность высокоуровневых функций, используя [инлайн функции](inline-functions.html).
Иногда выгодно улучшить производительность функций высшего порядка, используя [инлайн функции](inline-functions.html).
<a name="lambda-expressions-and-anonymous-functions"></a>
<!--Lambda Expressions and Anonymous Functions-->
## Лямбда-выражения и анонимные функции
<!--A lambda expression or an anonymous function is a "function literal", i.e. a function that is not declared, but passed immediately as an expression. Consider the following example:-->
Лямбда-выражения или анонимные функции являются ~~"функциональными константами"~~<i>(ориг. "functional literal")</i>, то есть функциями, которые не были объявлены, но сразу были переданы в качестве выражения. Рассмотрим следующий пример:
Лямбда-выражение, или анонимная функция, это "функциональный литерал", то есть необъявленная функция, которая немедленно
используется в качестве выражения. Рассмотрим следующий пример:
``` kotlin
max(strings, { a, b -> a.length < b.length })
```
<!--Function max is a higher-order function, i.e. it takes a function value as the second argument. This second argument is an expression that is itself a function, i.e. a function literal. As a function, it is equivalent to-->
Функция `max` является функцией высшего порядка, потому что она принимает функцию в качестве второго аргумента.
Этот второй аргумент является выражением, которое в свою очередь есть функция, то есть <i>функциональный литерал</i>.
Как функция он эквивалентен объявлению:
Функция `max` - высокоуровневая функция, так как она принимает другую функцию в качестве входного аргумента. Этот второй аргумент является выражением, которое само по себе представляет из себя функцию, то есть <i>functional literal</i>.
``` kotlin
fun compare(a: String, b: String): Boolean = a.length < b.length
```
<!--Function Types-->
## Типы функций
## Функциональные типы
Чтобы функция могла принять функцию в качестве параметра, необходимо указать тип функции-параметра.
Например, вышеуказанная функция `max` определена так:
<!--For a function to accept another function as a parameter, we have to specify a function type for that parameter. For example the abovementioned function max is defined as follows:-->
Для того, чтобы функция принимала другую функцию в качестве входного параметра, нам необходимо указать её (входящей функции) тип. К примеру, вышеуказанная функция `max` определена следующим образом:
``` kotlin
fun <T> max(collection: Collection<T>, less: (T, T) -> Boolean): T? {
var max: T? = null
@@ -125,14 +138,13 @@ fun <T> max(collection: Collection<T>, less: (T, T) -> Boolean): T? {
}
```
<!--The parameter less is of type (T, T) -> Boolean, i.e. a function that takes two parameters of type T and returns a Boolean: true if the first one is smaller than the second one.-->
Параметр 'less' является `(T, T) -> Boolean` типом, то есть функцией, которая принимает два параметра типа `T` и возвращает 'Boolean':'true', если первый параметр меньше, чем второй.
Параметр `less` является `(T, T) -> Boolean` типом, то есть функцией, которая принимает два параметра типа `T` и возвращает Boolean: 'true',
если первый параметр меньше второго.
В теле функции, строка 4, `less` используется как функция: она вызвана с двумя параметрами типа `T`.
<!--In the body, line 4, less is used as a function: it is called by passing two arguments of type T.-->
В теле функции, строка 4, `less` используется в качестве функции: она вызывается путём передачи двух аргументов типа `T`.
Функциональный тип записывается, как указано выше, или может иметь именованые параметры, если нужно выявить смысл каждого из параметров.
<!--A function type is written as above, or may have named parameters, if you want to document the meaning of each parameter.-->
Тип функции может быть написан так, как указано выше, или же может иметь определённые параметры, если вы хотите обозначить значения каждого из параметров.
``` kotlin
val compare: (x: T, y: T) -> Int = ...
```

0 comments on commit 7590b79

Please sign in to comment.