Когда частичная функция scala не является частичной функцией? - PullRequest
8 голосов
/ 20 мая 2010

При создании карты String для частичных функций я столкнулся с неожиданным поведением. Когда я создаю частичную функцию в качестве элемента карты, она работает нормально. Когда я выделяю val, он вызывает вместо этого. Попытка вызвать проверку приводит к ошибке. Это ожидается? Я делаю что-то глупое? Закомментируйте check(), чтобы увидеть вызов. Я использую scala 2.7.7

def PartialFunctionProblem() = {
    def dream()() = {
        println("~Dream~");
        new Exception().printStackTrace()
    }
    val map = scala.collection.mutable.HashMap[String,()=>Unit]()
    map("dream") = dream()      // partial function
    map("dream")()              // invokes as expected
    val check = dream()         // unexpected invocation
    check()                     // error: check of type Unit does not take parameters 
}

Ответы [ 2 ]

12 голосов
/ 20 мая 2010

Для удобства Scala позволяет опускать пустые парены при вызове метода, но достаточно умен, чтобы увидеть, что ожидаемый тип в первом случае равен ()=>Unit, поэтому он не удаляет все парены для вас; вместо этого он преобразует метод в функцию для вас.

В случае val check, однако, это выглядит как результат вызова функции, присваиваемой переменной. Фактически, все три из них делают то же самое:

val check = dream
val check = dream()
val check = dream()()

Если вы хотите превратить метод в функцию, вы ставите _ после метода вместо списка аргументов . Таким образом,

val check = dream() _

будет делать то, что вы хотите.

5 голосов
/ 20 мая 2010

Ну, проблема в том, что вы все неправильно поняли. : -)

Вот некоторые концептуальные ошибки:

def dream()() = {
    println("~Dream~");
    new Exception().printStackTrace()
}

Это не частичная функция. Это карри метод с двумя пустыми списками параметров, который возвращает Unit.

val map = scala.collection.mutable.HashMap[String,()=>Unit]()

Тип значений на этой карте - не частичная функция, а функция. В частности, Function0[Unit]. Частичная функция будет иметь тип PartialFunction[T, R].

map("dream") = dream()      // partial function

В данном случае Scala преобразует частично примененный метод в функцию. Это не простое задание. Scala выполняет преобразование, потому что модуль вывода типов может угадать правильный тип.

val check = dream()         // unexpected invocation

Здесь нет ожидаемого типа, который помог бы в выводе типов. Однако пустые списки параметров могут быть опущены, так что это всего лишь вызов метода.

...