Что такое каррирование функций в Python?

Ответ

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

Концепция

Вместо вызова f(a, b, c) вы последовательно вызываете f(a)(b)(c). Это позволяет "зафиксировать" часть аргументов и передавать получившуюся функцию дальше.

Пример в Python

Хотя Python не поддерживает каррирование "из коробки", его можно реализовать вручную или использовать functools.partial для достижения похожего эффекта — частичного применения.

from functools import partial

# Исходная функция
def add(x, y, z):
    return x + y + z

# 1. Ручная реализация каррирования
def curry_add(x):
    def inner1(y):
        def inner2(z):
            return x + y + z
        return inner2
    return inner1

# Использование
add_10 = curry_add(10)
add_10_and_5 = add_10(5)
result = add_10_and_5(3) # 18
print(f"Результат каррирования: {result}")

# 2. Идиоматичный способ через partial (частичное применение)
add_10_partial = partial(add, 10)
result_partial = add_10_partial(5, 3) # 18
print(f"Результат с partial: {result_partial}")

Основные преимущества:

  • Переиспользование кода: Позволяет создавать специализированные функции из более общих.
  • Композиция: Упрощает объединение функций в цепочки вызовов.
  • Читаемость: В некоторых случаях улучшает читаемость кода, особенно в функциональном стиле.

Ответ 18+ 🔞

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

Вот смотри, есть у тебя функция, которая жрёт три цифры разом: f(a, b, c). А каррирование говорит: "Да похуй, давай не сразу, а по одной, как конфеты из вазочки". И превращает вызов в вот эту цепочку: f(a)(b)(c). Каждая скобочка — это как новый заход, новый уровень вложенности, новый пиздёц, прости Господи.

Зачем это, спрашивается, надо?

А чтобы, сука, "зафиксировать" часть аргументов заранее. Сделал себе заготовку, как полуфабрикат, и потом только докидываешь оставшееся. Удобно, блядь, переиспользовать.

Вот тебе живой пример на Python

Питон, конечно, не Haskell, чтоб из коробки так уметь, но мы не лыком шиты. Сделаем сами, с блэкджеком и вложенными функциями.

from functools import partial

# Обычная функция, складывает три числа
def add(x, y, z):
    return x + y + z

# 1. Каррирование вручную, по-деревенски
def curry_add(x):
    def inner1(y):
        def inner2(z):
            return x + y + z
        return inner2
    return inner1

# Используем. Сначала фиксируем 10
add_10 = curry_add(10)
# Потом фиксируем 5
add_10_and_5 = add_10(5)
# И наконец докидываем 3
result = add_10_and_5(3) # 18
print(f"Результат каррирования: {result}")

# 2. Нормальный, идиоматичный способ через partial (частичное применение)
# Тут мы просто приколачиваем первый аргумент гвоздём
add_10_partial = partial(add, 10)
# И потом дополняем остальными
result_partial = add_10_partial(5, 3) # 18
print(f"Результат с partial: {result_partial}")

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

И в чём же, блядь, профит?

  • Переиспользование, ёпта: Сделал из общей функции умножить(число, коэффициент) специализированную удвоить(число), зафиксировав коэффициент как 2. Красота!
  • Композиция: Удобнее собирать функции в паровозики, когда они ждут по одному аргументу.
  • Читаемость: Иногда такой стиль делает код понятнее, особенно если мозги уже заточены под функциональщину. Хотя, честно, иногда выглядит как выёбистое программирование просто ради выёбистости.

Короче, инструмент как инструмент. Знать надо, а применять — с умом, а не чтобы просто похвастаться, что ты в теме, блядь.