Узнайте, что такое функции высшего порядка и почему они важны в функциональном программировании, и напишите несколько примеров на Python и JavaScript.

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

Функции обычно получают в качестве входных данных значения, такие как числа, строки и ссылки или копии объектов и списков, и при необходимости могут возвращать значения в этих типах.

Но подождите, а что, если, например, мы реализуем функцию timer, которая по прошествии X секунд выполнит заданный кусок кода? Может ли такая функция timer иметь на входе другую функцию?

Что такое функции высшего порядка?

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

Как большой поклонник функционального программирования, я люблю функции высшего порядка. Они полезны для написания более читаемого и простого в обслуживании кода. И эту парадигму я часто использую при работе с JavaScript/TypeScript, особенно при работе с React. Хотя, должен признать, я не так много использовал его при работе с Python.

Функции высшего порядка великолепны, но…

Зачем мне использовать функции высшего порядка?

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

Вы когда-нибудь работали с методами filter, map, forEach в JavaScript? Это отличные примеры функций JavaScript более высокого порядка.

Написание ваших первых функций высшего порядка

Начнем просто с создания двух разных функций высшего порядка. Первый будет принимать функцию в качестве входных данных, а второй пример будет возвращать функцию. Далее мы напишем собственные определения для некоторых наиболее популярных функций высшего порядка, имена некоторых из которых мы уже назвали ранее.

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

Принятие функции в качестве аргумента

Для начала давайте создадим очень простую функцию `doOperation`, которая принимает 3 аргумента:

  • Работа функции
  • номер 1
  • номер 2

Кроме того, мы создадим операцию с именем sumBothNumbers, которая просто вернет сумму двух чисел.

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

Питон:

def doOperation(operation, number1, number2):
    return operation(number1, number2)

def sumBothNumbers(number1, number2):
    return number1 + number2

doOperation(sumBothNumbers, 3, 5)

------------
Output
------------
8

JavaScript:

function doOperation(operation, number1, number2) {
    return operation(number1, number2)
}

function sumBothNumbers(number1, number2) {
    return number1 + number2
}

doOperation(sumBothNumbers, 3, 5)

------------
Output
------------
8

Возврат функции

Далее мы построим функцию более высокого порядка, которая возвращает функцию. Наша функция будет называться multiplyBy, она примет число в качестве аргумента и вернет функцию, которая умножит свой ввод на это число.

Питон:

def multiplyBy(multiplier):
    def result(num):
        return num * multiplier
    return result

multiplyByThree = multiplyBy(3)
multiplyByThree(4)

------------
Output
------------
12

JavaScript:

function multiplyBy(multiplier) {
    return function result(num) {
        return num * multiplier
    }
}

multiplyByThree = multiplyBy(3)
multiplyByThree(4)

------------
Output
------------
12

Построение Filter(), Map() и Reduce()

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

Чтобы повысить уровень наших навыков работы с функциями высшего порядка, мы напишем код для некоторых из самых популярных методов работы с массивами в парадигме функционального программирования.

фильтр() или фильтрация()

Функция filtering будет иметь 2 параметра: функцию array и функцию test. Он вернет новый массив со всеми элементами, прошедшими проверку.

Питон:

def filtering(arr, test):
    passed = []
    for element in arr:
        if (test(element)):
            passed.append(element)
    return passed

def isSuperNumber(num):
    return num >= 10

filtering([1, 5, 11, 3, 22], isSuperNumber)

------------
Output
------------
[11, 22]

JavaScript:

function filtering(arr, test) {
    const passed = []
    for (let element of arr) {
        if (test(element)) {
            passed.push(element)
        }
    }
    return passed
}

function isSuperNumber(num) {
    return num >= 10
}

filtering([1, 5, 11, 3, 22], isSuperNumber)

------------
Output
------------
> (2) [11, 22]

карта(), также известная как отображение()

Функция mapping` будет принимать 2 параметра: функцию array` и функцию transform`, и она вернет новый преобразованный массив, каждый элемент которого является результатом функции transform`, вызываемой для каждого элемента исходного массива.

Питон:

def mapping(arr, transform):
    mapped = []
    for element in arr:
        mapped.append(transform(element))
    return mapped

def addTwo(num):
    return num+2

mapping([1, 2, 3], addTwo)

------------
Output
------------
[3, 4, 5]

JavaScript:

function mapping(arr, transform) {
    const mapped = []
    for (let element of arr) {
        mapped.push(transform(element))
    }
    return mapped
}

function addTwo(num) {
    return num + 2
}

mapping([1, 2, 3], addTwo)

------------
Output
------------
> (3) [3, 4, 5]

уменьшить () или уменьшить ()

Функция reducing будет принимать 3 параметра: функция reducer, initial value для аккумулятора и array. Для каждого элемента массива вызывается функция редьюсера, передавая его аккумулятору и текущему элементу массива. Возвращаемое значение присваивается аккумулятору. После сокращения всех элементов в списке возвращается накопленное значение.

Питон:

def reducing(reducer, initial, arr):
    acc = initial
    for element in arr:
        acc = reducer(acc, element)
    return acc

def accum(acc, curr):
    return acc + curr

reducing(accum, 0, [1, 2, 3])

------------
Output
------------
6

JavaScript:

function reducing(reducer, initial, arr) {
    let acc = initial
    for (element of arr) {
        acc = reducer(acc, element)
    }
    return acc
}

function accum(acc, curr) {
    return acc + curr
}

reducing(accum, 0, [1, 2, 3])

------------
Output
------------
6

Часто задаваемые вопросы

Почему они называются функциями высшего порядка?

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

Что такое функциональное программирование?

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

Являются ли функции высшего порядка общей темой на собеседованиях?

Да, функции высшего порядка — частая тема на собеседованиях по разработке программного обеспечения, это зависит от роли программиста и языка, но, вообще говоря, полезно это знать. Они являются важным аспектом функционального программирования и написания кода с учетом масштабируемости и повторного использования. Знание того, как писать и использовать функции высшего порядка, важно для разработчиков программного обеспечения, которые хотят работать с современными веб-приложениями или мобильными приложениями.

Заключение

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

Сегодня я впервые представил статью, охватывающую более одного языка. Если вы считаете, что это отличный способ продемонстрировать и сравнить их, или если вы считаете, что это была ужасная идея, сообщите мне об этом в комментариях или в Твиттере. Я хотел бы услышать ваши идеи.

Спасибо за прочтение!

Подпишитесь на мою еженедельную рассылку для разработчиков и строителей и получайте еженедельную электронную почту с актуальным контентом.

Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу