2013-03-10 13 views
7

Per esempio, Exception.allCatch è definito comePerché alcuni metodi di Scala usano argomenti polimorfici invece di usare Qualsiasi/Niente?

def allCatch[T]: Catch[T] 

Perché non solo

val allCatch: Catch[Nothing] 

quando Catch è covariante nel suo argomento?

Oppure, perché PartialFunction oggetto definisce

def empty[A, B]: PartialFunction[A, B] 

invece di

val empty: PartialFunction[Any,Nothing] 

?

Aggiornamento: Finora sembra che le risposte non siano all'altezza. Quindi, per favore, includi nella tua risposta degli esempi specifici che mirano davvero alla domanda. Ad esempio: mostra un pezzo di codice che funziona con def empty[A, B]: PartialFunction[A, B] ma non funziona (o è meno conveniente) con val empty: PartialFunction[Any,Nothing].

+0

Penso che dovresti aggiornare la tua domanda per includere il motivo per cui è importante. – nilskp

+0

@nilskp Sono curioso del design delle librerie. In particolare, quando creo il mio codice, dovrei usare le varianti polimorfiche o quelle con "Any/Nothing"? –

risposta

2

Ciò evita la necessità di eseguire il casting in un secondo momento e consente di trattare il tipo di args come T anziché Any, che di solito è più conveniente.

Ecco un esempio:

scala> def func1[T](arg : T) : T = { arg } 
func1: [T](arg : T)T 

scala> def func2(arg : Any) : Any = { arg } 
func2: (arg: Any)Any 

scala> func1(4) 
res4: Int = 4 

scala> func2(4) 
res7: Any = 4 
+1

Il tuo esempio è corretto, non ci sono dubbi, ma non risponde alla mia domanda. Implica un parametro di tipo invariante: puoi riformularlo come 'def func1 [T]: T => T = (arg: T) => arg'. Qui ovviamente non possiamo evitare il parametro type - qualsiasi tentativo di questo tipo renderebbe la funzione meno generale. Ma la mia domanda mira ai tipi con i parametri del tipo di variante co (ntra). Forse affronti direttamente gli esempi che ho fornito nella mia domanda. –

2

Se hard-code il tipo, come PartialFunction[Any,Nothing], non è possibile restringere la funzione di prendere un parametro più specifico di Any.

Utilizzando un parametro di tipo generico, è possibile ritrovarsi con una soluzione più flessibile che soddisfa tutti i casi e soprattutto rende sicura la funzione.

Supponiamo che tu desideri una funzione che desideri prendere un Animal come parametro e restituire un Integer.

Supponiamo che la funzione è dichiarata come essere:

def myFunction: PartialFunction[Any,Nothing] 

In primo luogo, funzione parziale non sarebbe specializzato per Animal al fianco dei parametri, ma a Any. Che dire se passo uno Human come parametro ...., passerebbe .. E riguardo la sicurezza?

In secondo luogo, se questa funzione viene dichiarata come restituita Nothing, non è possibile restituire alcun valore ma Nothing! Infatti, Nothing sottoclasse tutte le classi in Scala. Ciò porta alla regola nota che il parametro type restituito deve sempre essere covariante per rendere una funzione interessante, non il caso con Nothing.

In effetti, Nothing è interessante solo quando si tratta del metodo empty di PartialFunction. Logica dal momento che un vuoto PartialFunction non implica nulla da restituire e dovrebbe essere costretto a farlo :)

Si potrebbe chiedere: "Allora perché non cambiamo il tipo di ritorno a Any?" Risposta: Perché si perderebbe tutto il vantaggio del tempo di cancellazione generica facendo compilatore per aggiungere automaticamente i cast necessari => Non si recupera direttamente il valore intero, ma Any. Fastidioso ..

+0

Potresti per favore elaborare la tua risposta e includere alcuni esempi? –

+0

Aggiornato con ulteriori spiegazioni. – Mik378

+2

Sento che non risponde ancora alla mia domanda. Naturalmente, non vi è alcun significato nel dichiarare una funzione che fa qualcosa come "PartialFunction [Any, Nothing]'. Ma non era quello che chiedevo. La mia domanda è: perché non dichiariamo la singola funzione 'empty' con questo tipo? Non legge alcun input e non restituisce mai un valore. Quindi avere il suo tipo "[Any, Nothing]' è perfettamente sicuro. Inoltre, a causa della varianza co (ntra), viene automaticamente convertito in qualsiasi tipo '[A, B]' per qualsiasi 'A' e' B'. –

2

Guardando la fonte di PartialFunctionavailable here possiamo vedere che in realtà chiama un metodo privato sull'oggetto PartialFunction:.

private[this] val empty_pf: PartialFunction[Any, Nothing]

Quindi il tipo di ritorno di vuoto sarà sempre PartialFunction[Any, Nothing] per quanto riguarda il ragionamento che sta dietro non ho idea Forse qualcuno. altrimenti hai una migliore comprensione del perché. Puoi provare il langua mailing list ge ...

1

In realtà, sembra che la libreria standard di Scala abbia alcuni punti in cui il parametro di tipo generico è ridondante (a causa della varianza di tipo). Ad esempio, vedere il mio question su foreach. La mia ipotesi, basata sulla risposta di @ Peter, è che questi generici ridondanti rendono l'interfaccia più chiara. Grazie a loro, non dobbiamo ricordare quali tipi sono covarianti, controvarianti e invarianti. Inoltre, questo rende le cose più semplici per le persone che non hanno familiarità con la varianza, che è piuttosto una funzionalità avanzata di Scala.

+0

Grazie, 'foreach' è un altro bel esempio. –

Problemi correlati