2013-03-08 9 views
10

In Scala, perché è possibile passare facilmente una funzione al curry direttamente ad altre funzioni, ma quando lo si assegna a uno val, è necessario applicarlo parzialmente anche con _? Ad esempio, date le due funzioni:Perchè Scala richiede l'applicazione parziale delle funzioni al curry quando si assegna a una val?

def curried(a: Int)(b: Int) = a + b 
def test(a: Int, f: Int => Int) = f(a) 

posso facilmente passare curried-test con:

test(5, curried(5)) 

e tutto è felice. Tuttavia, se ho semplicemente chiamo curried(5) ottengo un errore:

scala> curried(5) 
<console>:9: error: missing arguments for method curried; 
follow this method with `_' if you want to treat it as a partially applied function 
       curried(5) 

Se cambio la chiamata a includere informazioni sul tipo tuttavia, funziona:

val 'curried: Int => Int = curried(5) 

Qualcuno può spiegare il razionale dietro l'inconsistenza, sicuramente il Il compilatore di Scala può dedurre che la funzione sia Int => Int data la definizione del tipo sul metodo originale?

+0

Nel caso 'val' se si specifica un'annotazione di tipo non è necessario l'applicazione parziale parziale' _'. –

risposta

8

Il problema non è dedurre il tipo, il problema è dedurre il tuo intento. Hai commesso un errore o hai intenzionalmente curry la funzione?

Purtroppo la sintassi di sottolineatura finale è la sintassi formale, e omettendola è lo zucchero sintattico.

+0

Questo ha senso, ma sicuramente il fatto che ho dichiarato il metodo come una funzione al curry ha già descritto il mio intento. Se il problema è nell'intento deduttivo, perché è corretto per l'inlining? –

+0

@MarkDerricutt Non sono sicuro di cosa intendi per "inlining", ma in tutti i casi hai mostrato dove funziona hai dichiarato ciò che ti aspettavi, quindi Scala va avanti con il curriculum perché corrisponde alle tue aspettative. Per quanto riguarda il primo, Scala non curry implicitamente, ma retry esplicitamente con underscore finale o se i tipi corrispondono - se provieni da una lingua con curriculum implicito che potrebbe sembrare innaturale. La funzione _declaration_, tuttavia, dichiara più elenchi di parametri, che è utile per altre cose oltre alla conversione. –

+0

Con "inlining" intendevo l'uso nella posizione dell'argomento (pensandoci su, l'assegnazione all'argomento ha informazioni di tipo complete, quindi è essenzialmente la stessa del mio ultimo esempio). Avevo pensato che il curriculum esplicito di Scala venisse dalle liste di argomenti multipli, a differenza dell'approccio di Haskell dove ogni dichiarazione di metodo è implicitamente curata, e ogni chiamata con argomenti mancanti restituisce semplicemente la funzione al curry in quella posizione. La mia confusione deriva dal presupposto che "liste di parametri multipli == currying", ovviamente questo non è il caso specifico. –

0

Il trattino di sottolineatura non è sempre necessario. Da http://docs.scala-lang.org/cheatsheets/

val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd 

currying, sintassi evidente.

def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd 

currying, sintassi evidente

def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd 

currying, la sintassi di zucchero. ma poi:

val normer = zscore(7, 0.4) _ 

necessità finale di sottolineatura per ottenere il parziale, solo per la versione di zucchero.