Немного карри


Использовать карринг в Scala одно удовольствие.
Само определение каррирования(или карринга, названо в честь Хаскелла Карри):

Для функции h типа h : (A × B) → C оператор каррирования Λ выполняет преобразование
Λ(h) : A → (B → C)

Отметим, что Λ – это оператор, то есть “функция над функциями”.
Например берем функцию foo(x,y), каррируем и получаем moo(x)(y) – функцию от x которая возвращает функцию от y.

Таким образом мы можем сводим программу к вычислению функции от одного аргумента.

Чтобы выполнить карирование, можно вызвать Function.curried. Сейчас это уже устаревший метод, т.к. curried можно вызывать сразу у функции.

Небольшой пример (для наглядности в императивном стиле):

scala> val foo = (x:Int,y:Int) => x + y  // функция от 2(ДВУХ) аргументов x и y.
scala> foo(1,2) // просто сложили и получили три
scala> val moo = foo.curried   // получили функцию от 1(ОДНОГО) аргумента, которая возвращает
scala> val zoo = moo(1)         // функцию от 1(ОДНОГО) аргумента
scala> zoo(2) //  урраа! получили три
scala> // можно каррировать и так:
scala> def noo(x:Int, y:Int) = x * y
scala> val a = noo _ // получили функцию от 2-х аргументов (подробнее см. partially applied function)
scala> val b = a.curried
scala> b(2) // = фунция 2 * аргумент 
scala> b(2)(3) // = 6

Метод curried можно найти в трейтах начиная от Function2 и заканчивая Function22.
Это значит, что вы можете использовать его для функций от 2 аргументов и до функций с 22-аргументами включительно.

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

Для функций с более чем 22-мя не поддерживается (таких трейтов вообще нет).
Например если Вы захотите сделать:
val foo = (x0:Int,x1:Int и т.д. до x22:Int) => 0
то получите ошибку компиляции:
implementation restricts functions to 22 parameters“.

Чтобы не возникало путаницы, поясню.

  • Во-первых:
    Это не значит, что вы не можете объявлять методы
    def foo(x0:Int,x1:Int и т.д. до x22:Int) = 0
    Это будет работать, но использовать в полную “силу” возможности Scala по работе с функциями уже не получится.
    Можно считать, что это “обычный” метод с 23 аргументами…
  • Во-вторых:
    Функции с varargs (переменным количество аргументов) работают нормально. Здесь никаких проблем с каррирование быть не должно.
  • В-третьих:
    Если у вас функции с более чем 22 аргументами это π#_!@#?!!!
    Думаете такого не бывает? Когда-то я работал в организации, в которой нужно было писать и разбираться со скриптами на лиспе (было и такое в моей жизни). Так вот, некоторые умельцы декларировали функции от 15-ти и более аргументов.
    Я в очередной раз взываю ко всем программистам с планеты Земля.
    Пожалуйста, постарайтесь так больше не делать. Уж очень неприятно работать с таким кодом.
Любое использование либо копирование материалов или подборки материалов сайта, элементов дизайна и оформления допускается лишь с разрешения правообладателя и только со ссылкой на источник: programador.ru

Телеграм канал: @prgrmdr
Почта для связи: vit [at] programmisty.com