2013-08-23 6 views
3

У меня есть определение следующих методов:Curried функции в Скале

def add1(x: Int, y: Int) = x + y 

def add2(x: Int)(y: Int) = x + y 

второй является кэррите версию первого. Тогда, если я хочу частично применить вторую функцию, мне нужно написать val res2 = add2(2) _. Все отлично. Затем я хочу, чтобы add1 функция была точной. Я пишу

val curriedAdd = (add1 _).curried 

я прав, что curriedAdd является похож на add2? Но когда я пытаюсь частично применить curriedAdd таким образом val resCurried = curriedAdd(4) _ Я получаю ошибку компиляции. Тогда я фиксирую его

val resCurried = curriedAdd(4) 

Почему результат Functions.curried отличается от выделанной версии оных функции (от add2)?

ответ

4

Во-первых curriedAdd такое же, как и add2 _ не add2. add2 - всего лишь метод.

scala> curriedAdd 
res52: Int => (Int => Int) = <function1> 

scala> add2 _ 
res53: Int => (Int => Int) = <function1> 

О втором вопросе. Я думаю, что это причина. Производство

scala> val i = curriedAdd(23) 
i: Int => Int = <function1> 

scala> i _ 
res54:() => Int => Int = <function0> 

scala> curriedAdd(23) _ 
<console>:10: error: _ must follow method; cannot follow Int => Int 
       curriedAdd(23) _ 

curriedAdd(23) _ не работает. Давайте посмотрим на лестницу руководства (§6.7) -

Выражение е _ хорошо сформированным, если е имеет тип метода или, если е является вызов по имени параметра. Если e - метод с параметрами, e_ представляет e, преобразованный в тип функции путем расширения eta (§6.26.5). Если e является параметром без параметров или параметром call-by-name типа => T, e_ представляет функцию типа() => T, которая вычисляет e, когда применяется к пустым параметрическому списку().

Помните, что оценивает только если это метод или вызов по имени параметра.В curriedAdd(23) _ он не оценивает curriedAdd (23), но проверяет, является ли это методом или вызовом по имени. Это не метод, а параметр call-by-name.

Это не по имени потому по имени является свойство переменной. Над вами вы получите по-имени после оценки curriedAdd(23), но curriedAdd(23) сам по себе не является по-имени переменной. Следовательно, ошибка (в идеале компилятор должен был ее скрыть). Обратите внимание, что ниже работ:

scala> curriedAdd(23) 
res80: Int => Int = <function1> 

scala> res80 _ 
res81:() => Int => Int = <function0> 

Вышеприведенные работает, потому что res80 _, здесь вы подаете _ к вызова по имени параметра и, следовательно, делает преобразование.

0

Чтобы ответить на этот вопрос, давайте посмотрим на REPL.

Сначала мы определяем две функции, как и вы.

scala> def add1(x: Int, y: Int) = x + y 
add1: (x: Int, y: Int)Int 

scala> def add2(x: Int)(y: Int) = x + y 
add2: (x: Int)(y: Int)Int 

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

scala> val curriedAdd = (add1 _).curried 
curriedAdd: Int => (Int => Int) = <function1> 

Вы только что создали частичную прикладную функцию, которая ожидает параметр один и возвращает частичную прикладную функцию типа Int => Int. Это не похоже на add2, как вы ожидаете.
Чтобы достичь того же для add2, вам нужно будет позвонить

scala> val curriedAdd2 = add2 _ 
curriedAdd2: Int => (Int => Int) = <function1> 
+1

Это не отвечает на вопрос. 'curriedAdd (4) _' не работает, но' val i = curriedAdd (4); i _' работает. – Jatin

+0

Вопрос был: «Почему результат функции Functions.curried отличается от карновой версии функции add (от add2)?» Думаю, я указал на различия. –

 Смежные вопросы

  • Нет связанных вопросов^_^