Почему частичная функция, примененная к двум функциям, которые выполняют одно и то же действие, определенное двумя различными способами, возвращает другой результат? - PullRequest
7 голосов
/ 03 марта 2012

Я могу определить следующие две функции:

def add(a: Int, b: Int, c: Int) = a + b + c

это приводит к

add: (a: Int, b: Int, c: Int)Int

и

val add2 = (a: Int, b: Int, c: Int) => a + b + c

это приводит к

add2: (Int, Int, Int) => Int = <function3>

Обе эти функции выполняют одну и ту же функцию, но определяются по-разному, но я не понимаю, если я продолжу и определю частично примененную функцию следующим образом:

def a = add _

Это приводит к

a: (Int, Int, Int) => Int = <function3> 

, как и ожидалось, функции, которая принимает 3 параметра и возвращает Int, но если я делаю

def a2 = add2 _

, это приводит к

a2: () => (Int, Int, Int) => Int = <function0>

которая выглядит как функция, которая не принимает параметров и возвращает функцию, которая принимает 3 параметра Int и возвращает Int.Почему это происходит?Может кто-нибудь объяснить, что происходит?

спасибо

Ответы [ 3 ]

9 голосов
/ 03 марта 2012

Это странный побочный эффект того, что Scala не имеет (доступных для пользователя) полей, а вместо этого имеет средства доступа (получатели) для всего. Обратите внимание:

scala> val i = 1
i: Int = 1

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

Причина в том, что i на самом деле является средством доступа (def i: Int) к базовому (скрытому, недоступному) полю. Так как это всего лишь метод, _ преобразует его в функцию. Метод доступа не принимает никаких аргументов, поэтому у вас есть функция, которая не принимает параметров.

2 голосов
/ 03 марта 2012

Scala имеет функции и методы, они не совсем одно и то же.

def add(a: Int, b: Int, c: Int) = a + b + c

Который определил метод (не функцию !!).

val add2 = (a: Int, b: Int, c: Int) => a + b + c

Который присвоил add2 значение функции (а не метод !!).

Метод не может быть конечным значением, тогда как функция может:

scala> add
<console>:9: error: missing arguments for method add;
follow this method with `_' if you want to treat it as a partially applied function
              add
              ^

scala> add2
res1: (Int, Int, Int) => Int = <function3>

scala> val a = add
<console>:8: error: missing arguments for method add;
follow this method with `_' if you want to treat it as a partially applied function
       val a = add
               ^

scala> val a2 = add2
a2: (Int, Int, Int) => Int = <function3>

Запись подчеркивания после имени метода может явным образом преобразовать метод в функцию:

scala> add _
res2: (Int, Int, Int) => Int = <function3>

Но если вы пишете подчеркивание после значения, оно преобразуется в функцию, которая не принимает аргументов с типом возвращаемого значения его типа:

scala> val s = ""
s: String = ""

scala> val i = 1
i: Int = 1

scala> s _
res3: () => String = <function0>

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

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

scala> add2 _
res5: () => (Int, Int, Int) => Int = <function0>
1 голос
/ 03 марта 2012

Эффект четко описан в Ответ Рекса Керра , но вы должны отметить, что add2 - это значение, уже представляющее частично примененную функцию, например делегат.Для демонстрации вы можете сравнить типы add1 _ выражения и add2 значения.

scala> def getManifest[T](x:T)(implicit m:scala.reflect.Manifest[T]) = m
getManifest: [T](x: T)(implicit m: scala.reflect.Manifest[T])scala.reflect.Manifest[T]

scala> getManifest(add1 _) == getManifest(add2)
res14: Boolean = true
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...