2013-03-29 15 views
9

C'è modo di abbinare parzialmente un tuple senza dover specificare la dimensione? Per esempio, se ho avuto una tuplaCorrisponde a una tupla di dimensioni sconosciute in scala

val v = ("Dr", "John","H", "Watson") 

mi piacerebbe essere in grado di fare qualcosa di simile:

v match { 
    case ("Dr", : _*) => "What's up, Doc?" 
    case ("Mr", name, :_*) => s"Welcome, Mr. ${name}" 
    case _ => "Have we met?" 
} 

Questo non si compila, :_* normalmente significa un numero indeterminato di parametri, ma non può essere usato in questo caso apparentemente. L'idea sarebbe di essere in grado di utilizzare questo matcher per qualsiasi tuple più grande di 2. So che posso farlo convertendo v in un List (per esempio) prima, voglio solo sapere se è possibile farlo con uno tuple.

EDIT: la maggior parte delle informazioni che ho trovato sul web è this discussion, che risale al Scala 2.8, in modo da sto andando con il 'No, non si puo' rispondere.

+0

Per quanto ne so, non c'è modo, perché le tuple di diverse dimensioni sono di diverso tipo. Ma può essere fatto con macro: l'obiettivo è generare un codice che corrisponda a tutte le dimensioni possibili. O come hai suggerito, definisci le conversioni implicite in 'Seq [Any]'. Anche questa è una soluzione sporca, e faresti meglio a chiedertelo, le tuple sono il tipo giusto da usare nel tuo problema? Forse non lo sono. –

+1

@SargeBorsch ma tutti estendono Prodotto ;-) –

+0

@ om-nom-nom Sì, è vero, ma se si digita Product, non si conoscono i tipi dei suoi elementi e quindi si perde l'accesso typesafe ai propri dati (è necessario per controllare manualmente/eseguire il cast dei tipi dei suoi elementi) –

risposta

11

Le tuple sono strutture per tipi eterogenei. Come tali, essi attuano il productIterator tratto, in modo che si possa fare:

v.productIterator.toList match { 
    case "Dr" :: _ => "What's up, Doc?" 
    case "Mr" :: name :: _ => s"Welcome, Mr. ${name}" 
    case _ => "Have we met?" 
} 

Ma il vostro esempio Sembra veramente si vuole un Seq[String] subito. C'è qualche ragione per voler usare le tuple?

+1

Come indicato nella domanda, voglio solo sapere se è possibile, non ci sono motivi particolari per usare le tuple. In realtà non ho bisogno di farlo affatto, solo di essere curioso: D – Chirlo

+1

Quindi la risposta breve è "no", le tuple di diverse entità non condividono nulla tra loro tranne che fornire un 'Iterator [Qualsiasi]'. –

10

Questo può essere fatto utilizzando shapeless 's conversioni da tuple a HLists,

scala> import shapeless._ 
import shapeless._ 

scala> import Tuples._ 
import Tuples._ 

scala> val v = ("Dr", "John","H", "Watson") 
v: (String, String, String, String) = (Dr,John,H,Watson) 

scala> v.hlisted match { 
    | case "Dr" :: _ => "What's up Doc?" 
    | case "Mr" :: name :: _ => s"Welcome, Mr. ${name}" 
    | case _ => "Have we met?" 
    | } 
res0: String = What's up Doc? 

Anche se non è visibile nell'esempio di cui sopra, si segnala che, ove possibile, le informazioni di tipo statico completo è mantenuto per i nomi legati alla clausole caso, ad esempio,

scala> (23, "foo", true).hlisted match { 
    | case i :: s :: b :: HNil => if(b) i+s.length else 0 
    | case _ => -1 
    | } 
res1: Int = 26 
-1

Prova questa:

case tuple:Product => { 
    tuple.productIterator.toList match { 
     case (head::rest) => ... 

    } 
} 
Problemi correlati