2014-04-29 8 views
6

Ho il seguente codice:Scala "non prende i parametri" quando pattern-corrispondenza parametrica caso classe

sealed trait A 

case class B[T](v: T) extends A 
case class C[T](v: T) extends A 

object Test { 
    def swap(a: A): A = a match { 
    case a: B[t] => C[t](a.v) // works! 
    case C[t](v) => B[t](v) // error: C[t] does not take parameters 
    } 
} 

mi si aspetterebbe entrambi entrambi i casi di fallire o di entrambi al lavoro. Qual è il significato dell'errore per il secondo caso? Esiste una case history parametrica destrutturante della sintassi?

Nota: qui, 't' in minuscolo è essenziale. Se fosse "T", il controllore lo cercerebbe nei parametri tipo del metodo.

+0

Questo è anche il caso quando si esegue l'estrazione per vals, cioè 'val C [T] (v) = ...' – ggovan

+0

Giusto per essere sicuro di capire il codice ... si sta usando 't' per rappresentare un tipo? Quando per convenzione i tipi sono rappresentati con una lettera maiuscola iniziale? E, per confondere ulteriormente, stai usando il parametro 'v' per mantenere il valore per l'argomento' v'? Per favore, rendi il tuo codice un po 'meno ... autoreferenziale. –

+1

@BobDalgleish: L'uso di una lettera maiuscola per il tipo causerebbe un errore qui, e l'utilizzo del collegamento 'v' a' a.v' non mi sembra così terribile. –

risposta

6

Quando si esegue a match { case C(v) => ??? }, in realtà si chiamano unapply metodo dell'oggetto C compagno, qualcosa di simile: C.unapply(a) match {Some(v) => ???}

C'è solo un C oggetto, non un'intera famiglia di C[t]. Non esiste alcun oggetto a cui è possibile fare riferimento come C[Int], quindi case C[t](v) => non ha senso.

Nell'esempio, si utilizza B[t] come tipo, non come modello, ed è per questo che funziona. Si noti che mentre la partita può avere successo, non si otterrà nulla in t, a causa della cancellazione dei tipi.

Quando si chiama C[t](a.v), quindi prima di tutto, compilatore cancella digitare t in ogni caso, e in secondo luogo, questo viene riscritto ad una chiamata al apply metodo sull'oggetto compagna: C.apply[t](a.v). Si noti che il parametro type si trova sulla chiamata al metodo, non sull'oggetto.

+0

Le due risposte si completano a vicenda - questo è più dettagliato, ma è un po 'poco chiaro sulla cancellazione e "perché" B [t] funziona in questo modo. L'altro spiega con un riferimento reale il comportamento (nel riferimento, ci sono esempi che illustrano e spiegano esattamente cosa succede rispetto alla cancellazione del tipo: quale delle due risposte dovrei accettare? – comco

+1

Il più dettagliato/popolare. – ggovan

1

In poche parole, non fa parte della lingua.

Se utilizzato in questa posizione, il compilatore cerca il tipo nell'ambiente, come se fosse un normale tipo maiuscolo. Il tipo di acquisizione che stai tentando di eseguire sembra funzionare solo nel modulo case x:Y[z] => ... di un'istruzione case.

Il tipo di acquisizione in questo modo non è una parte ben conosciuta della lingua e mi ha richiesto di accedere allo Scala reference document per i dettagli (Sezione 8.3). Personalmente trovo che la distinzione tra maiuscolo e minuscolo qui non sia di mio gradimento.

Nell'esempio t assume il tipo di Any poiché le informazioni sul tipo per il parametro non sono disponibili da A.

Problemi correlati