2010-03-01 5 views
11

Ho visto questo utilizzo dell'esempio Function.tupled in un altro answer: Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length).Sintassi function.tupled e segnaposto

Funziona:

scala> Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length) 
<console>:5: warning: method tupled in object Function is deprecated: 
Use `f.tuple` instead 
     Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length) 
               ^
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3) 

Sembra che posso fare a meno se non voglio usare la sintassi segnaposto.

scala> Map(1 -> "one", 2 -> "two") map (x => x._1 -> x._2.length) 
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3) 

L'uso diretto della sintassi segnaposto non funziona:

scala> Map(1 -> "one", 2 -> "two") map (_._1 -> _._2.length) 
<console>:5: error: wrong number of parameters; expected = 1 
     Map(1 -> "one", 2 -> "two") map (_._1 -> _._2.length) 

lavoro Come funziona Function.tupled? Sembra che stia succedendo molto nello Function.tupled(_ -> _.length). Inoltre come dovrei usarlo per non ottenere l'avviso di deprecazione?

+0

@huynhjl La deprecazione di Function.tupled è il risultato di una comprensione che una funzione deve sapere come creare una tupla senza aiuto. Tuttavia, questo in realtà non funziona bene con l'inferenza di tipo. Spero davvero che non rimuoveranno Function.tupled senza rendere il tipo inferencer abbastanza intelligente da aggirare questo problema. –

+0

L'ho sottovalutato per ora. – extempore

risposta

15

UPDATE Il ritiro è stato removed oggi, in risposta a questo problema.


Tupling una funzione è semplicemente adattando FunctionN[A1, A2, ..., AN, R] ad un Function1[(A1, A2, ..., AN), R]

Function.tuple è deprecato in favore di FunctionN#tupled. A (forse involontaria) conseguenza di ciò è che il tipo inferencer non può dedurre i tipi di parametri in:

scala> Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled     
<console>:5: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$minus$greater(x$2.length)) 
     Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled 
             ^
<console>:5: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$minus$greater(x$2.length)) 
     Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled 

Qualcuno di questi funzionerà:

scala> Map(1 -> "one", 2 -> "two") map { case (a, b) => a -> b.length } 
res8: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3) 

scala> Map(1 -> "one", 2 -> "two") map ((_: Int) -> (_: String).length).tupled   
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3) 

scala> Map(1 -> "one", 2 -> "two") map ((p: (Int, String)) => p._1 -> p._2.length) 
res12: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3) 

vi consiglio di leggere le risposte a questo recente domanda per ottenere una comprensione più profonda della '_' in letterali funzione, e come funziona tipo inferenze:

In Scala, what is the difference between using the `_` and using a named identifier?

UPDATE

In risposta al commento, lo fa.

scala> val f = (x:Int, y:String) => x + ": " + y 
f: (Int, String) => java.lang.String = <function2> 

scala> f.tupled 
res0: ((Int, String)) => java.lang.String = <function1> 

scala> Map(1 -> "1") map f.tupled 
res1: scala.collection.immutable.Iterable[java.lang.String] = List(1: 1) 

Ciò richiede Scala 2.8. Si noti che la mappa Map # può risultare in un'altra mappa, se il tipo di ritorno della funzione è un Tuple2, altrimenti una lista, come sopra.

+0

Grazie per la risposta. Ciò che mi confonde è che questo non funziona: 'val f = (x: Int, y: String) => x +": "+ y; f.tupled'. Non dovrebbe restituire una versione di f che funziona su una tupla (Int, String)? – huynhjl

+0

ok, vedo, questo spiega molto. Ho ripetuto il test con 2.8.0.Beta1 e funziona come previsto. Ho provato prima con 2.8.0.Beta1-RC5 che avevo nel mio percorso. Ho bisogno di liberarmi di RC5 ... – huynhjl