8

Al crear un mapa de Cadena para funciones parciales, encontré un comportamiento inesperado. Cuando creo una función parcial como un elemento de mapa, funciona bien. Cuando asigno a un valor, invoca en su lugar. Intentar invocar el cheque genera un error. Es esto esperado? ¿Estoy haciendo algo tonto? Comente el check() para ver la invocación. Estoy usando Scala 2.7.7¿Cuándo una función parcial scala no es una función parcial?

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

Gracias por la ayuda. Cuando reemplacé mis llamadas de sueño() con dream() _ se comportó como esperaba. Saldré y leeré más sobre PartialFunctions para no volver a usar mal el término. –

Respuesta

12

Para mayor comodidad, Scala le permite omitir parens vacías al llamar a un método, pero es lo suficientemente inteligente como para ver que el tipo esperado en el primer caso es ()=>Unit, por lo que no hace eliminar todos los parens para usted; en cambio, convierte el método en una función para ti.

En el caso val check, sin embargo, se ve como un resultado de llamada a función que se asigna a una variable. De hecho, los tres de estos hacen exactamente lo mismo:

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

Si desea activar el método en una función, se coloca _ después del método en lugar de la lista (s) argumento. Por lo tanto,

val check = dream() _ 

hará lo que quiera.

5

Bueno, el problema es que lo has entendido mal. :-)

Éstos son algunos errores conceptuales:

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

Ésta no es una función parcial. Este es un método curry con dos listas de parámetros vacíos que devuelve Unit.

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

El tipo de los valores en este mapa no es función parcial, sino función. Específicamente, Function0[Unit]. Una función parcial tendría el tipo PartialFunction[T, R].

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

Lo que sucede aquí es que Scala convierte el método aplicado parcialmente en una función. Esta no es una simple tarea. Scala realiza la conversión porque el tipo inferencer puede adivinar el tipo correcto.

val check = dream()   // unexpected invocation 

No hay ningún tipo esperado para ayudar al tipo inferencer. Sin embargo, las listas de parámetros vacías se pueden omitir, por lo que esta es solo una llamada a un método.

Cuestiones relacionadas