[БЕЗ_ЗВУКА] [МУЗЫКА] Как мы с вами обсуждали раньше, в языке Котлин есть много различных особенностей, облегчающих написание кода. Сейчас на примере работы со списками мы познакомимся с одной из самых полезных на практике особенностей — функциями высших порядков. Пойдем от примера. Нашу функцию invertPositives можно написать намного проще, если сформулировать задачу чуть более декларативно, то есть описательно. Что мы хотим сделать? Пройтись по списку и к каждому элементу применить функцию, которая изменяет знак для положительных элементов на обратный, а для отрицательных оставляет элемент как есть. Обход списка и получение результате тут — второстепенные операции. Суть задачи заключается именно в функции преобразовании. Чтобы иметь возможность реализовать такой алгоритм в виде кода, нам необходимо уметь передавать функции, как аргументы в другие функции. Именно такие функции и называются функциями высших порядков. Для списка, например, есть функция map, которая принимает другую функцию, применяет ее по очереди к каждому элементу списка и собирает результаты в новый список. С ее помощью invertPositivies можно переписать вот так. Анонимная функция, которую мы передаем в map, описывает трансформацию одного элемента, а работу по обходу списка и формированию результату берет на себя функция map. И это позволяет писать более компактный и при этом понятный код, поскольку вы можете сосредоточиться на описании того, что действительно важно — того, как вы хотите преобразовать элемент списка. Остальное будет сделано за вас. Если вы думаете, что таким образом нельзя преобразовать элементы из одного типа в другой, то это не так. Если вы хотите превратить список чисел в список соответствующих им строковых представлений, например, это также можно сделать при помощи функции высших порядков map. Получается достаточно простое, компактное и понятное решение, но его можно записать еще короче, если воспользоваться так называемыми лямбда-функциями. Лямбда-функция — это специальная разновидность анонимной функции, которая записывается компактнее, без указания имени функции, имени и типа аргумента за счет следующих предположений. В качестве имени параметра используется имя it — сокращенное от iterator, или итератора — специального типа объектов для перебора элементов у структур данных. Если вы все же хотите указать имя параметра, это можно сделать при помощи следующей записи. Тип параметра считается равным типу, который должен быть у соответствующей функции обработки элементов. Для map — это тип элемента списка. Тип результата по аналогии принимается таким, чтобы удовлетворять требованию функции высших порядков. Для map, так как она превращает исходные элементы в другие, он может быть любым. Если тело лябмда-функции состоит из одной операции — а это достаточно частая ситуация для реального применения функции высших порядков, — то ее результатом считается результат этой самой операции. В противном случае результатом считается результат последней операции в теле лямбды. И в том, и в другом случае оператор return не используется. В качестве финального штриха: в случае если лямбда является последним аргументом функции высшего порядка, то при вызове ее можно вынести за скобки и писать вот так. Пустые круглые скобки вызова также можно опустить, получив в итоге следующую — совсем-совсем компактную запись. Вам может показаться, что функции высших порядков — это сложно, но на самом деле они достаточно просты и понятны. Главное — это не задумываться о том, как именно они устроены внутри. Давайте посмотрим, как с их помощью можно решить еще несколько задачек. Представим, что мы хотим теперь уже не поменять знак у всех положительных чисел, а просто удалить их из списка. Для такой операции фильтрации элементов предназначена функция filter, с помощью которой нашу задачу можно решить вот так вот — всего лишь в одну строчку кода. В качестве аргумента функция filter принимает другую функцию-предикат, которая берет элемент, возвращает для него либо true, если мы хотим оставить элемент в списке, либо false, если элемент следует отфильтровать. В качестве более сложного примера можно рассмотреть задачу определения того, является ли число простым или нет. Ее можно решить вот так вот при помощи функции all, которая проверяет верность другой функции для всех элементов из того набора, над которым ее вызвали. В нашем случае условие простоты выглядит как число не делится на один из возможных делителей, которые находятся в интервале от 2 до n / 2 и которые и перебирает наша функция all. В качестве результата она возвращает true в том и только в том случае, если для всех элементов функция-предикат также вернула true. В противном случае будет возвращен false. Кто-то может спросить: а что функция all вернет для пустого списка? Ответ на этот вопрос можно узнать либо в документации к языку Котлин, либо проведя простой эксперимент самостоятельно. А теперь давайте посмотрим на в каком-то смысле самую мощную из функций высших порядков — функцию свертки fold. В полном соответствии с названием эта функция сворачивает список в какой-либо аккумулятор при помощи функции-свертки, которая принимает на вход уже два параметра: текущий аккумулятор, уже обработанный к данному моменту, и следующий элемент. В качестве результата она должна вернуть новое значение аккумулятора. Почему функция свертки самая мощная, можете спросить вы. Потому что с ее помощью можно реализовать практически любую другую полезную на практике функцию высших порядков. Да-да, в том числе и рассмотренные нами ранее функции map и filter, например следующим образом. Давайте попробуем рассмотреть функцию, которая берет список чисел и возвращает результат их перемножения. Через функцию fold это можно сделать вот так. В качестве результата мы используем результат перемножения чисел, то есть действительное число типа double. В качестве начального значения аккумулятора используется 1.0. Функция свертки берет значение аккумулятора, умножает его на текущий элемент и возвращает получившийся результат в качестве следующего нового значения аккумулятора. После того как мы обработали весь список, итоговое значение аккумулятора возвращается как результат всей функции fold. И если вы все же не до конца понимаете, что такое функции высших порядков и как их использовать, не переживайте. Любой код, написанный с их помощью, всегда можно переписать так, чтобы он не использовал фукнции высших порядков. Самое главное для вас сейчас — научиться основам программирования. А умение использовать те или иные возможности придет с опытом. Для тех из вас, кто хочет разобраться в функциях высших порядков чуть более подробно, рекомендую обратиться вот сюда в соответствующий раздел референса языка Котлин. До встречи! [БЕЗ_ЗВУКА]