8

Podczas tworzenia mapy funkcji String na częściowe natknąłem się na nieoczekiwane zachowanie. Kiedy tworzę częściową funkcję jako element mapy, to działa dobrze. Kiedy przydzielam do wartości val, wywołuje ona zamiast tego. Próba wywołania kontroli generuje błąd. Czy to jest oczekiwane? Czy robię coś głupiego? Skomentuj numer check(), aby wyświetlić wywołanie. Używam Scala 2.7.7Kiedy funkcja częściowa scala nie jest funkcją częściową?

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 
} 
+0

Dzięki za pomoc. Kiedy zamieniłem swoje rozmowy marzeń() ze snem() _ zachowywało się tak, jak się spodziewałem. Wyjdę i przeczytam więcej o PartialFunctions, więc nie użyję ponownie tego terminu. –

Odpowiedz

12

Dla wygody Scala umożliwia pominięcie pustych nawiasów podczas wywoływania metody, ale jest na tyle sprytny, aby zobaczyć, że spodziewany typ w pierwszym przypadku jest ()=>Unit, więc nie usuń wszystkie parens dla ciebie; zamiast tego konwertuje metodę na funkcję dla ciebie.

W przypadku val check wygląda tak, jak wynik wywołania funkcji przypisany do zmiennej. W rzeczywistości, wszystkie trzy z nich zrobić dokładnie to samo:

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

Jeśli chcesz włączyć metodę do funkcji, należy umieścić _ po metody zamiast listy argumentów (ów). Tak więc, zrobi to, co chcesz.

5

Problem polega na tym, że wszystko jest w porządku. :-)

Oto niektóre błędy koncepcyjne:

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

To nie jest częściowym funkcja. Jest to metoda curry z dwoma pustymi listami parametrów, która zwraca Unit.

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

Typ wartości na tej mapie nie jest funkcją cząstkową, ale funkcją. W szczególności, Function0[Unit]. Funkcja częściowa miałaby typ PartialFunction[T, R].

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

Co się dzieje, jest to, że Scala konwertuje częściowo stosowanej metody do funkcji. To nie jest proste zadanie. Scala wykonuje konwersję, ponieważ inferencer typów może odgadnąć poprawny typ.

val check = dream()   // unexpected invocation 

Tutaj nie ma oczekiwanego typu, który mógłby pomóc w wypełnieniu formularza. Jednak puste listy parametrów mogą zostać pominięte, więc jest to po prostu wywołanie metody.