2015-09-22 23 views
8

In Scala si possono fare cose come:funzione dei parametri impliciti non più così dopo il passaggio ad una funzione di ordine superiore

def foo(implicit v: Int) = println(v); 
def h(x: Int) = { implicit val i: Int = x; foo } 

h(42) 
> 42 

h chiamata ottiene foo di riferimento come chiusura.

Non sarebbe strano per cercare passando foo-h come parametro:

def g(x: Int)(f: Int => Unit) = { implicit val i: Int = x; f } 

Ma non avrebbe funzionato:

g(1)(foo) 
> error: could not find implicit value for parameter v: Int 

Quello che penso che sta accadendo è che foo ottiene chiamato come una valutazione del parametro attuale. È giusto?

Quando superato una funzione con un normale elenco di parametri (non implicito), non si sta valutando la funzione:

def foo2(v: Int) = println("Foo2") 
g(1)(foo2) 
> Int => Unit = <function1> 

Questo è un risultato atteso e foo2 valutazione non è provato come una valutazione di un effettivo parametro.

Perché foo viene valutato come un parametro effettivo quando non sono disponibili valori impliciti per farlo?

stesso avviene per assegnazione:

val fooref: Int => Unit = foo 
> error: could not find implicit value for parameter v: Int 

È come dato Int => Unit non corrisponde con una funzione in cui il parametro Int è contrassegnato come implicito, il compilatore scartano come parametro effettivo valido e quindi cerca per valutarlo. Non trovare un valore implicito dichiarato per soddisfare la chiamata.

Se questo è il caso, quale sarebbe il modo di esprimere il tipo di una funzione con parametri impliciti?

risposta

11

Sfortunatamente, le funzioni non possono avere parametri impliciti: solo i metodi possono.

Nell'espressione g(1)(foo), foo viene convertito da un metodoad una funzione (noto anche come eta-espansione). E section 6.26.2 delle Specifiche di Scala afferma che gli argomenti impliciti sono applicati prima di eta-espansione.

Vedi questo biglietto: implicit methods behave suboptimally when used non-implicitly

1

Il tipo del parametro f di funzionare g è Function1[Int, Unit]. Function1[A, B] è un tratto con il metodo singolo apply(a: A): B, dove a non è implicito. Quindi, non è possibile creare un'istanza di Function1[Int, Unit] da foo - non avrebbe la firma corretta.

Problemi correlati