Ответ 1
Это забавная вещь в функциональном программировании под названием currying. В основном Моисей Шонфинкель и последний Хаскелл Карри (Schonfinkeling звучат странно, хотя...) придумали идею о том, что вызов функции из нескольких аргументов, например f(x,y)
, совпадает с цепочкой вызовов {g(x)}(y)
или g(x)(y)
, где g
- это функция, которая выдает другую функцию.
В качестве примера возьмем функцию f(x: Int, y: Int) = x + y
. Вызов f(2,3)
вызвал бы 5
, как и ожидалось. Но что происходит, когда мы выполняем эту функцию - переопределяем ее как f(x:Int)(y: Int)
и называем ее f(2)(3)
. Первый вызов f(2)
создает функцию с целым числом y
и добавляет к ней 2
→ поэтому f(2)
имеет тип Int => Int
и эквивалентен функции g(y) = 2 + y
. Второй вызов f(2)(3)
вызывает вновь созданную функцию g
с аргументом 3
, поэтому оценивая 5
, как и ожидалось.
Еще один способ его просмотра - переступить редукцию (функциональные программисты называют это бета-редукцию - он похож на функциональный способ поэтапного перехода по строке) вызова f(2)(3)
(обратите внимание, что это не действительно действительно Scala).
f(2)(3) // Same as x => {y => x + y}
|
{y => 2 + y}(3) // The x in f gets replaced by 2
|
2 + 3 // The y gets replaced by 3
|
5
Итак, после всего этого разговора f(x)(y)
можно рассматривать как просто следующее lambda выражение (x: Int) => {(y: Int) => x + y}
- которое действительно Scala.
Я надеюсь, что все это имеет смысл - я попытался дать немного информации о том, почему вызов modN(3)
имеет смысл:)