Перейти к основному содержимому
02МОБИЛКА · ГЛАВА 02Функции и лямбдыλ(x)

Функции и лямбды

Прочитано 0%Квизы 0/4Тренажёры 0/6Уровень 1 · Новичок

Зачем это нужно

В прошлой главе мы уже пользовались готовыми функциями — println, listOf, map, sum — и даже написали свою первую лямбду внутри map { it * 2 }. Мы знали, как их вызывать, но не разбирали, как устроена функция изнутри и как написать свою.

Функция (function) — это именованный кусок кода, который можно вызвать сколько угодно раз с разными входными данными. Без функций код, который считает бонус за очки, пришлось бы копировать в каждое место, где он нужен: на экране игрока, в отчёте тренера, в уведомлении о победе. С функцией это один кусок кода в одном месте — и вызов по имени везде, где он нужен.

В этой главе разберём объявление функции по символам — что значит каждый знак сигнатуры, — научимся задавать параметры по умолчанию (default arguments) и именованные аргументы (named arguments), напишем собственные лямбды разных форм и разберёмся, что такое функция высшего порядка (higher-order function) на примере map и filter, которые уже видели в главе 1.

Функция по кусочкам: fun square(x: Int): Int

Вот функция, которая возводит число в квадрат. Разберём сигнатуру — первую строку, где объявлены имя, параметры и тип возврата, — по символам.

KOTLIN · ФУНКЦИЯ КАК КОРОБКАx = 4входsquare(x)x * x16выход{ x -> x * x }та же коробка без имени — лямбда: тот же вход → выход, только анонимно
Функция — коробка: вход слева, тело внутри, выход справа. Лямбда — та же коробка без имени.
Нажми на часть выражения

Что означает каждый символ

  • fun — ключевое слово: объявляет функцию. Как и val/var, это слово нельзя использовать как имя переменной или функции.
  • скобки ( ) — список параметров (parameters): переменных, которые функция получает при вызове. Пустые скобки () означают, что функция параметров не принимает — так была устроена main() в главе 1.
  • : Тип после скобок — тип возврата (return type): что функция отдаёт наружу. Если функция ничего не возвращает — этот раздел можно опустить, разберём чуть ниже.
  • параметр и аргумент — разные слова. Параметр (parameter) — это имя в объявлении функции (x в fun square(x: Int)). Аргумент (argument) — конкретное значение, которое передают при вызове (4 в square(4)). Одно описывает место, другое — то, что в это место кладут.
KOTLIN · СИГНАТУРА ФУНКЦИИ ПО ЧАСТЯМfunsquareимя(x: Intпараметры):Intтип возвратаимя — параметры со своими типами — тип возврата: три части между fun и {
Сигнатура функции по частям: имя — параметры со своими типами — тип возврата. Три части между словом fun и открывающей скобкой тела.

Теперь тело функции — то, что происходит внутри фигурных скобок, — и вызов.

fun main() { println(square(4)) } fun square(x: Int): Int { return x * x }

Разбор по строкам

  • Строки 1–3: fun main() { ... } — точка входа, как в главе 1. Внутри — единственный вызов square(4), обёрнутый в println.
  • Строка 5: fun square(x: Int): Int { — объявление функции square: принимает один параметр x типа Int, возвращает Int. Открывающая { начинает тело — список команд, которые выполнятся при вызове.
  • Строка 6: return x * x — новое ключевое слово return: «немедленно закончи функцию и отдай наружу то, что справа». Здесь отдаётся x * x — квадрат переданного числа.
  • Строка 7: } — конец тела функции.
Интересный факт

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

Что выведет: 16 — потому что square(4) вычислил 4 * 4 и вернул это значение в println.

Тело-выражение: одна строка вместо блока

Если тело функции — это ровно одно выражение, фигурные скобки и return можно убрать, заменив их знаком =. Это называется телом-выражением (expression body) — в противовес телу-блоку (block body), которое мы только что видели.

Нажми на часть выражения
fun main() { println(square(4)) } fun square(x: Int): Int = x * x

Что выведет: 16 — то же самое число, что и в блочной версии: это два разных способа написать одну и ту же функцию.

У тела-выражения есть бонус: раз результат — это значение стоящего справа выражения, Kotlin может вывести его тип сам, точно так же, как выводил тип переменной по значению справа от =. Поэтому : Int можно вообще убрать.

fun main() { println(square(4)) } fun square(x: Int) = x * x

Что выведет: 16 — компилятор сам понял, что x * x — это Int, раз x типа Int, и присвоил такой же тип возврата функции. Это тот же вывод типов (type inference), что и у переменных, только применённый к функции.

Важно

Важно: этот трюк работает только для тела-выражения. У тела-блока (в фигурных скобках) тип возврата выводить неоткуда — Kotlin не станет анализировать все return внутри блока в поисках общего типа. Про это — отдельная ошибка в разделе «Типичные ошибки» ниже.

А что, если функции нечего возвращать — она просто что-то делает, например печатает текст? Тогда тип возврата вообще не пишут, и Kotlin считает его равным Unit — специальному типу «ничего не возвращаю».

fun main() { greet("Соня") } fun greet(name: String) { println("Привет, $name!") }

Разбор по строкам

  • Строка 5: fun greet(name: String) { — после скобок нет : Тип — значит, тип возврата не указан, и Kotlin подставляет Unit сам. Писать : Unit руками можно, но так не делают — это единственный тип, который по соглашению не пишут явно.
  • Строка 6 — функция просто печатает строку и ничего не отдаёт наружу через return.

Что выведет: Привет, Соня! — функция выполнила действие, но значения не вернула.

Отвечено вопросов: 0 из 4
Что означает : Int после скобок в fun square(x: Int): Int?
Чем тело-выражение (= x * x) отличается от тела-блока ({ return x * x })?
Можно ли не писать : Int в fun square(x: Int) = x * x?
Что вернёт fun greet(name: String) { println("Привет, $name!") }, если тип возврата не указан?
Отвечено верно: 0 из 4

Параметры по умолчанию: необязательные аргументы

Параметру можно задать значение по умолчанию (default argument) прямо в объявлении. Тогда при вызове его можно не передавать — Kotlin подставит значение сам.

Нажми на часть выражения
fun main() { greet("Олег") greet("Олег", "Здравствуй") } fun greet(name: String, greeting: String = "Привет") { println("$greeting, $name!") }

Разбор по строкам

  • Строка 2: greet("Олег") — передан только name; greeting не указан, поэтому берётся значение по умолчанию "Привет".
  • Строка 3: greet("Олег", "Здравствуй") — передано два аргумента, второй перекрывает значение по умолчанию.
  • Строка 6 — само объявление: greeting: String = "Привет" делает второй параметр необязательным.

Что выведет:

Привет, Олег!
Здравствуй, Олег!

Первый вызов взял значение по умолчанию, второй — то, что передали явно.

Обязательные параметры (без =) по соглашению ставят первыми, необязательные (со значением по умолчанию) — после них: это стиль, а не запрет компилятора. У параметра, который не в конце списка, тоже может быть значение по умолчанию — но тогда, чтобы пропустить его и задать следующий, понадобятся именованные аргументы, о которых дальше.

Именованные аргументы: вызов по имени, а не по порядку

Аргументы можно передавать не только по порядку, но и по имени параметра — тогда порядок вызова не важен, а из кода сразу видно, что чему соответствует.

Нажми на часть выражения
fun main() { describe(name = "ПГК", score = 100, isChampion = true) describe(score = 42, name = "Соня") } fun describe(name: String, score: Int, isChampion: Boolean = false) { println("$name: $score очков, чемпион: $isChampion") }

Разбор по строкам

  • Строка 2 — все три аргумента именованные, порядок совпадает с объявлением.
  • Строка 3 — аргументы переставлены местами (score раньше name) и один пропущен: isChampion не указан, значит берётся значение по умолчанию false. Именованные аргументы можно расставлять в любом порядке — Kotlin смотрит на имя слева от =, а не на позицию.
  • Строка 7 — обычное объявление функции с тремя параметрами, третий — со значением по умолчанию.

Что выведет:

ПГК: 100 очков, чемпион: true
Соня: 42 очков, чемпион: false
Совет

Заметь: name = "ПГК" при вызове и greeting: String = "Привет" при объявлении выглядят похоже, но это разные вещи. В объявлении имя: Тип = значение задаёт значение по умолчанию. При вызове имя = значение — это именованный аргумент, у него нет двоеточия и типа, потому что тип параметр уже получил при объявлении.

Проверь себя: здесь встречаются и значение по умолчанию, и именованные аргументы из этого раздела.

fun main() {
  greet("Соня")
  greet(greeting = "Здравствуй", name = "Олег")
}

fun greet(name: String, greeting: String = "Привет") {
  println("$greeting, $name!")
}

Что напечатает этот код? Сначала ответь, потом проверяй.

Отвечено вопросов: 0 из 4
Что делает greeting: String = "Привет" в объявлении параметра?
Что выведет greet("Олег"), если объявление — fun greet(name: String, greeting: String = "Привет")?
Зачем нужны именованные аргументы, если можно передавать значения просто по порядку?
Что выведет describe(score = 42, name = "Соня") для fun describe(name: String, score: Int, isChampion: Boolean = false)?
Отвечено верно: 0 из 4

Лямбды: с it и с именованными параметрами

В главе 1 мы уже писали numbers.map { it * 2 } — лямбду (lambda) с неявным параметром it. Освежим и пойдём глубже: что делать, если параметров несколько или it неудобно читать.

fun main() { val distances = listOf(3, 5, 4, 6, 2) val long = distances.filter { it > 4 } println(long) }

Разбор по строкам

  • Строка 3 — новый метод filter: пропускает каждый элемент через лямбду и оставляет в результате только те, для которых лямбда вернула true. it здесь — очередной элемент списка, it > 4 — сравнение «больше 4».
  • Что выведет: [5, 6] — только элементы длиннее 4 км остались в списке; filter, в отличие от map, не меняет сами значения, а решает, какие из них оставить.

Когда у лямбды не один параметр, а несколько, it уже не подходит — нужно назвать каждый явно и разделить их запятой перед стрелкой ->.

fun main() { val add: (Int, Int) -> Int = { a, b -> a + b } println(add(3, 4)) }

Разбор по строкам

  • Строка 2: val add: (Int, Int) -> Int = { a, b -> a + b } — слева от = объявлена переменная add с типом (Int, Int) -> Int: это тип функции (function type), который читается «принимает два Int, возвращает Int». Справа — сама лямбда: a, b — имена двух параметров, -> отделяет их от тела, a + b — тело.
  • Строка 3: add(3, 4) — лямбда, лежащая в переменной, вызывается точно так же, как обычная функция: именем и скобками с аргументами.

Что выведет: 7 — потому что 3 + 4 = 7.

Функции высшего порядка: map, filter и свои

Функция высшего порядка (higher-order function) — это функция, которая принимает другую функцию как параметр или возвращает функцию. map и filter из главы 1 — как раз такие: они принимают лямбду и решают, что с ней делать для каждого элемента.

fun main() { val distances = listOf(3, 5, 4, 6, 2) val longInMeters = distances.filter { it > 4 }.map { it * 1000 } println(longInMeters) }

Что выведет: [5000, 6000] — сначала filter оставил тренировки длиннее 4 км ([5, 6]), затем map перевёл их в метры. Каждый метод в цепочке — сам по себе функция высшего порядка: и filter, и map принимают лямбду параметром.

Посмотри в замедленной съёмке, как выполнение прыгает из main в функцию и обратно, а map прогоняет лямбду по каждому элементу:

1fun toMeters(km: List<Int>): List<Int> {
2 return km.map { it * 1000 }
3}
4
5fun main() {
6 val distances = listOf(3, 5, 4)
7 val meters = toMeters(distances)
8 println(meters)
9}

Нажимай «Шаг» и следи, как выполнение прыгает из main в функцию и обратно, а map прогоняет лямбду по каждому элементу.

Теперь напишем свою функцию высшего порядка — такую же, как filter/map внутри устроены сами.

Нажми на часть выражения
fun main() { println(calculate(6, 3, { a, b -> a + b })) println(calculate(6, 3) { a, b -> a - b }) } fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int { return operation(a, b) }

Разбор по строкам

  • Строка 5: сигнатура calculate — разобрана выше по символам.
  • Строка 6: return operation(a, b) — внутри calculate мы не знаем заранее, что за операция придёт: сложение, вычитание, что угодно. operation(a, b) вызывает то, что передали, как обычную функцию.
  • Строка 2: calculate(6, 3, { a, b -> a + b }) — лямбда передана третьим аргументом обычным способом, в скобках через запятую.
  • Строка 3: calculate(6, 3) { a, b -> a - b } — то же самое, но лямбда вынесена за скобки вызова. Такая запись называется трейлинг-лямбдой (trailing lambda): если лямбда — последний параметр функции, её можно писать не внутри ( ), а сразу после них.
Нажми на часть выражения
KOTLIN · ТРЕЙЛИНГ-ЛЯМБДА — ТА ЖЕ ЛЯМБДА СНАРУЖИвнутри скобок, третьим аргументомcalculate(6, 3, { a, b -> a - b })трейлинг: вынесена за круглые скобкиcalculate(6, 3){ a, b -> a - b }
Трейлинг-лямбда — та же самая лямбда, только вынесенная за круглые скобки вызова: содержимое не меняется, меняется только пунктуация.

Что выведет:

9
3

Первый вызов сложил (6 + 3 = 9), второй вычел (6 − 3 = 3) — потому что мы передали разные лямбды одной и той же функции calculate.

KOTLIN · calculate ПРИНИМАЕТ РАЗНЫЕ ЛЯМБДЫ{ a, b -> a + b }calculate(6, 3, op)9{ a, b -> a - b }calculate(6, 3, op)3{ a, b -> a * b }calculate(6, 3, op)18одна и та же calculate — три разных результата: сама она не знает, что делает op
Три разных лямбды в одном и том же параметре operation дают три разных результата: сама calculate не знает, что делает op.

А если той же calculate с теми же 6 и 3 передать третью лямбду — с умножением?

fun main() {
  println(calculate(6, 3) { a, b -> a * b })
}

fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
  return operation(a, b)
}

Что напечатает этот код? Сначала ответь, потом проверяй.

Теперь собери сигнатуры сам — от простой функции до функции высшего порядка:

Задание 1 из 3. Функция greet: принимает имя-строку, возвращает строку.

Кликай по кусочкам внизу в правильном порядке — сигнатура соберётся здесь
Отвечено вопросов: 0 из 4
Что такое функция высшего порядка (higher-order function)?
Что означает тип (Int, Int) -> Int?
Чем calculate(6, 3) { a, b -> a - b } отличается от calculate(6, 3, { a, b -> a - b })?
Что делает numbers.filter { it > 4 }?
Отвечено верно: 0 из 4

Типичные ошибки

Все четыре ошибки ниже — реальные сообщения из встроенной песочницы Kotlin Playground (той же, что работает в кнопках Run выше в этой главе). Тексты проверены вживую в этой сессии.

1. Значение из Unit-функции

fun main() { println(square(4)) } fun square(x: Int) { return x * x }
Return type mismatch: expected 'Unit', actual 'Int'.

Перевод: «Несовпадение типа возврата: ожидался Unit, а по факту Int». У square не указан тип возврата — значит, Kotlin считает его Unit («ничего»). А return x * x пытается вернуть Int. Обещание (неявное Unit) не совпало со значением.

Как починить: указать настоящий тип возврата — fun square(x: Int): Int { return x * x }, — либо, если функция правда ничего не должна возвращать, убрать return x * x и оставить только действие.

2. Забытый return в теле-блоке

fun main() { println(square(4)) } fun square(x: Int): Int { x * x }
Missing return statement.

Перевод: «Отсутствует оператор return». Функция обещала вернуть Int (: Int в сигнатуре), но тело-блок сам по себе ничего не возвращает — x * x здесь просто вычисляется и тут же забывается. В отличие от тела-выражения, тело-блок никогда не возвращает своё последнее выражение автоматически.

Как починить: добавить return явно — return x * x, — либо переписать функцию как тело-выражение: fun square(x: Int): Int = x * x.

3. Не передан обязательный аргумент

fun greet(name: String, greeting: String) { println("$greeting, $name!") } fun main() { greet("Олег") }
No value passed for parameter 'greeting'.

Перевод: «Не передано значение для параметра greeting». У greeting нет значения по умолчанию, поэтому он обязателен, а вызов greet("Олег") передаёт только один аргумент.

Как починить: передать оба аргумента — greet("Олег", "Привет"), — либо дать greeting значение по умолчанию в объявлении: greeting: String = "Привет".

4. Лямбда filter вернула не Boolean

fun main() { val numbers = listOf(1, 2, 3) val big = numbers.filter { it } println(big) }
Return type mismatch: expected 'Boolean', actual 'Int'.

Перевод: «Несовпадение типа возврата: ожидался Boolean, а по факту Int». Лямбда, переданная в filter, обязана отвечать на вопрос «оставить этот элемент?» — то есть возвращать Boolean (true/false). Здесь лямбда { it } просто отдаёт сам элемент, а он Int, а не Boolean.

Как починить: написать настоящее условие, дающее Boolean, например filter { it > 0 }.

Отвечено вопросов: 0 из 4
Почему fun square(x: Int) { return x * x } не компилируется?
Почему fun square(x: Int): Int { x * x } выдаёт "Missing return statement."?
Какую ошибку покажет компилятор для greet("Олег"), если оба параметра greet обязательны?
Почему numbers.filter { it } не компилируется для List<Int>?
Отвечено верно: 0 из 4

Символы главы

Шпаргалка по всем новым знакам и конструкциям этой главы.

Символ / конструкцияКак называетсяЧто делаетПример
funключевое словообъявляет функциюfun square(x: Int): Int
( ) после имени функциисписок параметровобъявляет входные данные функцииsquare(x: Int)
: после скобок функциианнотация типа возвратауказывает, что функция возвращает): Int {
returnключевое слововозвращает значение из тела-блока и завершает функциюreturn x * x
Unitтип «ничего»возвращаемый тип функций, которые не возвращают значение; пишется неявно, если : Тип пропущенfun greet(name: String) { ... }
= после сигнатуры функциитело-выражениезаменяет { return ... } на одну строку; тип возврата можно вывестиfun square(x: Int) = x * x
= значение внутри скобок параметрапараметр по умолчаниюделает аргумент необязательным при вызовеgreeting: String = "Привет"
имя = значение при вызовеименованный аргументявно указывает, какому параметру передаётся значение, независимо от порядкаdescribe(score = 42, name = "Соня")
{ a, b -> ... }лямбда с именованными параметрамистрелка отделяет параметры лямбды от тела{ a, b -> a + b }
itнеявный параметр лямбдыимя единственного параметра, если его не назвали явноfilter { it > 4 }
(Тип, Тип) -> Типтип функцииописывает сигнатуру лямбды/функции как значения(Int, Int) -> Int
fn(a, b) { ... }трейлинг-лямбдалямбда-последний-параметр выносится за круглые скобки вызоваcalculate(6, 3) { a, b -> a - b }
Углубиться

Unit — не пустота, а настоящий тип. В отличие от void в некоторых других языках, Unit в Kotlin — обычный тип с единственным значением (тоже называется Unit). Поэтому функцию, возвращающую Unit, формально можно использовать всюду, где ожидается значение, — например, передать её результат в println, и это не будет ошибкой. На практике так почти никогда не делают: Unit пишут (точнее, не пишут явно) для функций-действий, у которых важен побочный эффект, а не результат.

Замыкание (closure). Лямбда умеет обращаться не только к своим параметрам, но и к переменным, объявленным снаружи, — и даже изменять var-переменные, если они var. Например: var sum = 0; numbers.forEach { sum += it } — лямбда внутри forEach видит и меняет внешнюю sum. Это называется замыканием: лямбда «замыкает» вокруг себя часть окружающего кода. Работает это не только для лямбд, но и для локальных функций.

Дальше по теме:

  • Functions — официальная документация: параметры, тело-выражение, Unit, области видимости функций (member/local/extension)
  • Lambdas — официальная документация: функциональные типы, трейлинг-лямбды и раздел Closures подробнее

Слова главы

parameter
1 / 10

Потренируйся печатать

Сначала однострочная функция — тело-выражение:

Цель: скорость ≥ 110 зн/мин, точность ≥ 90%

fun square(x: Int): Int = x * x
клавиша ``клавиша 11клавиша 22клавиша 33клавиша 44клавиша 55клавиша 66клавиша 77клавиша 88клавиша 99клавиша 00клавиша --клавиша ==клавиша ⌫клавиша TabTabклавиша QQклавиша WWклавиша EEклавиша RRклавиша TTклавиша YYклавиша UUклавиша IIклавиша OOклавиша PPклавиша [[клавиша ]]клавиша \\клавиша Caps LockCaps Lockклавиша AAклавиша SSклавиша DDклавиша FFклавиша GGклавиша HHклавиша JJклавиша KKклавиша LLклавиша ;;клавиша ''клавиша EnterEnterклавиша ShiftShiftклавиша ZZклавиша XXклавиша CCклавиша VVклавиша BBклавиша NNклавиша MMклавиша ,,клавиша ..клавиша //клавиша ShiftShiftклавиша CtrlCtrlклавиша WinWinклавиша AltAltклавиша ПробелПробелклавиша AltAltклавиша WinWinклавиша MenuMenuклавиша CtrlCtrl
следующая: F — указательный левой руки

Теперь лямбда с типом функции и двумя именованными параметрами:

Цель: скорость ≥ 120 зн/мин, точность ≥ 90%

val add: (Int, Int) -> Int = { a, b -> a + b }

Куда дальше: проверенные ресурсы

Русские материалы с нуля

Официальный тур Kotlin (на английском)

  • Kotlin tour: Functions — официальный тур: сигнатура, именованные аргументы, значения по умолчанию, однострочные функции и лямбды со встроенными упражнениями и готовыми решениями.

Потренироваться

play.kotlinlang.org
Та же песочница, что работает в кнопках Run этой главы, но во весь экран.

Челлендж ⭐

Та же команда из главы 1 пробежала за неделю пять тренировок: listOf(3, 5, 4, 6, 2) километров.

Ступень 1. Напиши функцию totalLong(distances: List<Int>, threshold: Int = 4): Int, которая суммирует в метрах только те тренировки, что длиннее threshold километров. Используй цепочку .filter { }.map { }.sum() из этой главы и объяви функцию как тело-выражение (=, без фигурных скобок и return). Значение по умолчанию для threshold4.

Ступень 2 ⭐. Напиши функцию высшего порядка countBy(distances: List<Int>, predicate: (Int) -> Boolean): Int, которая возвращает количество тренировок, удовлетворяющих условию predicate. Вызови её с трейлинг-лямбдой, чтобы посчитать, сколько тренировок длиннее 4 км.

fun main() { val distancesKm = listOf(3, 5, 4, 6, 2) // ступень 1: замени 0 на вызов своей функции totalLong val totalLongMeters = 0 println("Метров в длинных тренировках: $totalLongMeters") // ступень 2 (со звёздочкой): напиши countBy и вызови её с трейлинг-лямбдой } // ступень 1: допиши функцию здесь // fun totalLong(distances: List<Int>, threshold: Int = 4): Int = ... // ступень 2 (со звёздочкой): допиши функцию здесь // fun countBy(distances: List<Int>, predicate: (Int) -> Boolean): Int = ...
Решение (сначала попробуй сам)

Ступень 1:

fun totalLong(distances: List<Int>, threshold: Int = 4): Int =
distances.filter { it > threshold }.map { it * 1000 }.sum()

Ступень 2 ⭐:

fun countBy(distances: List<Int>, predicate: (Int) -> Boolean): Int =
distances.filter(predicate).size

fun main() {
val distancesKm = listOf(3, 5, 4, 6, 2)
val totalLongMeters = totalLong(distancesKm)
println("Метров в длинных тренировках: $totalLongMeters")
val longCount = countBy(distancesKm) { it > 4 }
println("Длинных тренировок: $longCount")
}

Полный вывод:

Метров в длинных тренировках: 11000
Длинных тренировок: 2

5 и 6 км — единственные тренировки длиннее 4 км: (5 + 6) * 1000 = 11000 метров, и их ровно две.

Что должен уметь

  • Объявлять функцию с fun, параметрами и типом возврата, объясняя, что делает каждый символ сигнатуры.
  • Отличать тело-блок ({ return ... }) от тела-выражения (= ...) и знать, когда тип возврата можно не писать.
  • Объяснять, что такое Unit, и когда тип возврата опускают.
  • Задавать параметру значение по умолчанию и предсказывать, что произойдёт при вызове без этого аргумента.
  • Вызывать функцию с именованными аргументами — в произвольном порядке и пропуская параметры со значением по умолчанию.
  • Писать лямбду и с неявным параметром it, и с явно названными параметрами через ->.
  • Объяснять, что такое функция высшего порядка, и приводить пример на filter/map.
  • Писать свою функцию, принимающую лямбду как параметр через функциональный тип (Тип, Тип) -> Тип, и вызывать её через трейлинг-лямбду.
  • Узнавать по сообщению компилятора четыре типичные ошибки функций и лямбд — значение из Unit-функции, забытый return, непереданный обязательный аргумент, неверный тип результата лямбды — и чинить каждую.

Комментарии

Комментарии появятся после настройки. Нужен аккаунт GitHub — вход прямо в виджете выше.