Quando è una funzione parziale scala non una funzione parziale?
Domanda
Durante la creazione di una mappa di stringa per funzioni parziali ho incontrato un comportamento imprevisto. Quando creo una funzione parziale come un elemento della mappa funziona benissimo. Quando ho assegnare ad una val invoca invece. Cercando di invocare il controllo genera un errore. È questo previsto? Sto facendo qualcosa di stupido? Commentare la check()
per vedere l'invocazione. Sto usando 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
}
Soluzione
Per comodità, Scala consente di omettere svuota parentesi quando si chiama un metodo, ma è abbastanza intelligente per capire che tipo previsto nel primo caso è ()=>Unit
, in modo da non rimuovere tutte le parentesi per voi; invece, converte il metodo in una funzione per voi.
Nel caso val check
, tuttavia, sembra proprio come un risultato della funzione chiamata sempre assegnata a una variabile. In realtà, tutti e tre di questi fanno la stessa identica cosa:
val check = dream
val check = dream()
val check = dream()()
Se si desidera attivare il metodo in una funzione, si posiziona _
dopo che il metodo al posto della lista degli argomenti (s) . Così,
val check = dream() _
farà quello che vuoi.
Altri suggerimenti
Bene, il problema è che hai sbagliato tutto. : -)
Ecco alcuni degli errori concettuali:
def dream()() = {
println("~Dream~");
new Exception().printStackTrace()
}
Questa non è una funzione parziale. Questo è un metodo curry con due liste di parametri vuoti che restituisce Unit
.
val map = scala.collection.mutable.HashMap[String,()=>Unit]()
Il tipo di valori di questo mappa non è funzione parziale, ma funzione. Specificamente, Function0[Unit]
. Una funzione parziale avrebbe tipo PartialFunction[T, R]
.
map("dream") = dream() // partial function
Cosa accade è che Scala convertiti il metodo parzialmente applicato in una funzione. Questo non è un compito semplice. Scala esegue la conversione perché il tipo inferencer può indovinare il tipo corretto.
val check = dream() // unexpected invocation
Tipo Qui non c'è nessun dovrebbe aiutare il tipo inferencer. Tuttavia, elenchi di parametri vuoti possono essere omessi, quindi questo è solo una chiamata di metodo.