2013-02-08 26 views
6

Vorrei passare una chiusura a un metodo come opzione e sto facendo ciò che viene mostrato di seguito. Ottengo un errore di compilazione come mostrato di seguito. È possibile passare un parametro di chiusura opzionale a una funzione?Come passare un parametro di chiusura opzionale a una funzione?

def sampleMethod(a: String, b: String, optionalMethod: Option[(String, Int) => Unit]) { 
    // do some processing with a and b 
    optionalMethod match { 
     case Some(optionalMethod) => { 
     optionalMethod("a",3) 
     } 
     case _ 
     log("no optional method passed") 
    } 
} 

// definition of optMethod in some other place 
val optMethod = (c: String, d: Int) => { 
    // some processing with c, d and external values 
} 

// invoke 
sampleMethod("hi", "bye", optMethod) => FAILS TO COMPILE 

ERROR = type mismatch. expecting Option[(String, Int) => Unit] found (String, Int) => Unit 
+0

sampleMethod ("ciao", "ciao", alcuni (optMethod)) – twillouer

+0

facoltativoMethod.map (f => f ("a", 3)) per essere più chiaro – twillouer

+1

Solo perché altri linguaggi e le loro comunità di utenti sono sciatti con termino logy, non facciamo lo stesso qui. "Chiusura" si riferisce all'uso di variabili libere in una funzione letterale (nomi senza legami nel corpo di quella funzione) e tali riferimenti "si chiudono" nell'ambiente lessicale. Non tutte le funzioni implicano la chiusura nell'ambiente lessicale. Non tutte le funzioni sono letterali di funzione. Ad esempio, vengono spesso creati (automaticamente e in modo trasparente dal compilatore o esplicitamente) tramite "applicazione parziale" di un'altra funzione o di un metodo. –

risposta

3

Come su

sampleMethod("hi", "bye", Some(optMethod)) 
6

Come sottolineato in precedenza, il metodo si aspetta un valore Option contenente il optionalMethod. È necessario, quindi, superare un valore di Option ad esso:

// invoke with method 
sampleMethod("hi", "bye", Some(optMethod)) 
// invoke without method 
sampleMethod("hi", "bye", None) 

Se si vuole evitare il valore Option, si può provare il seguente (esp evitare il None.):

def sampleMethod(a: String, b: String, optionalMethod: (String, Int) => Unit = (_, _) => log("no optional method passed")) { 
    optionalMethod("a", 3) 
} 

// invoke with method 
sampleMethod("hi", "bye", optMethod) 
// invoke without method 
sampleMethod("hi", "bye") 
0

più chiaro:

scala> def sampleMethod(a: String, b: String, optionalMethod: Option[(String, Int) => Unit]) { 
    | optionalMethod.map(f => f("a", 3)) 
    | } 
sampleMethod: (a: String, b: String, optionalMethod: Option[(String, Int) => Unit])Unit 


scala> sampleMethod("A", "A", Some((c:String, d:Int) => println(s"Hello wolrd $c...$d"))) 
Hello wolrd a...3 

devi solo aggiungere "Alcuni()" in giro per la vostra funzione optinal

7

Il messaggio di errore è piuttosto esplicito: sampleMethod si aspetta un Option, ma si passa un valore di funzione diritta (non racchiuso in Some).

Il modo più semplice per risolvere questo problema è quello di avvolgere optMethod in un Some:

sampleMethod("hi", "bye", Some(optMethod)) 

Ma se si vuole essere in grado di fare semplicemente sampleMethod("hi", "bye", optMethod), si potrebbe aggiungere sovraccarico definizioni di sampleMethod:

object Test { 
    def sampleMethod(a: String, b: String, optionalMethod: Option[(String, Int) => Unit]) { 
    // do some processing with a and b 
    optionalMethod match { 
     case Some(optionalMethod) => { 
     optionalMethod("a",3) 
     } 
     case _ => log("no optional method passed") 
    } 
    } 
    def sampleMethod(a: String, b: String) { sampleMethod(a, b, None) } 
    def sampleMethod(a: String, b: String, optionalMethod: (String, Int) => Unit) { 
    sampleMethod(a, b, Some(optionalMethod)) 
    } 
} 

val optMethod = (c: String, d: Int) => { 
    // some processing with c, d and external values 
} 

// invoke 
Test.sampleMethod("hi", "bye", optMethod) // Now Compiles fine 
Test.sampleMethod("hi", "bye") // This too 
+0

Penso che l'overloading sia un approccio molto migliore dell'uso di 'Option' per l'argomento della funzione. –

+0

Vuoi dire usando solo 2 sovraccarichi (uno con l'argomento e uno senza) rispetto a 3 sovraccarichi come nella mia risposta? Se è così, la cosa è che nel caso generale potrebbe esserci un comportamento abbastanza comune tra entrambi i casi che si vuole ridurlo in una singola implementazione (come nel mio primo overload che fa tutto il lavoro), e abbastanza differenze che solo avere un il valore predefinito per 'optionalMethod' (come nella risposta di @fynn) potrebbe non essere sufficiente. Dipende molto dalle reali esigenze. –

+2

Quindi crea un metodo privato che fa il lavoro e prende l'opzione [Funzione] 'che viene poi chiamata dai metodi pubblici sovraccaricati con e senza' Funzione'. –

Problemi correlati