При создании карты Строки к частичным функциям я столкнулся с неожиданным поведением. Когда я создаю частичную функцию как элемент карты, это хорошо работает. Когда я выделяю 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
}
Для удобства Scala позволяет вам опускать пустые скобки при вызове метода, но он достаточно умен, чтобы видеть, что ожидаемый тип в первом случае - () => Unit
, поэтому он не удаляет все скобки за вас; вместо этого он преобразует метод в функцию для вас.
Однако в случае val check
это выглядит как результат вызова функции, присвоенный переменной. Фактически, все три из них делают одно и то же:
val check = dream
val check = dream()
val check = dream()()
Если вы хотите превратить метод в функцию, вы помещаете _
после метода вместо списка аргументов (s ) . Таким образом,
val check = dream() _
будет делать то, что вы хотите.
Проблема в том, что вы все неправильно поняли. : -)
Вот некоторые концептуальные ошибки:
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
Здесь нет ожидаемого типа, который мог бы помочь механизму вывода типов.Однако пустые списки параметров можно опустить, так что это просто вызов метода.