Perché il compilatore di Scala non può fornire un avviso di corrispondenza del modello per classi / tratti non sigillati?

10

Se uso un un sealed trait o abstract class in Scala e poi uso la corrispondenza dei pattern, mi chiedo, il compilatore non sa al momento della compilazione per questo particolare patternmatch quali possibili implementazioni di questo tratto / classe sono disponibili? Quindi, se lo fa, potrebbe non dare gli avvisi di corrispondenza del modello anche se il trait / abstract class non è sigillato perché sa quali tipi potrebbero essere usati, controllando tutte le possibili dipendenze / le importazioni?

es. se ho un Option[A] e faccio lo schema di corrispondenza solo per Some[A] ma non per None , il compilatore si lamenterà, perché Option è sigillato.

Se il compilatore non può sapere / risolvere ciò, allora perché non può? E se il compilatore (teoricamente) può farlo, quali sono le ragioni per cui non è usato in Scala? Esistono altri linguaggi che supportano questo tipo di comportamento?

    
posta valenterry 18.12.2014 - 13:08
fonte

2 risposte

15

L'identificazione di tutte le sottoclassi di una classe viene chiamata Analisi della gerarchia di classe e il CHA statico in una lingua con caricamento dinamico del codice equivale a risolvere il problema di interruzione.

Inoltre, uno degli obiettivi di Scala è la compilazione e l'implementazione separata di moduli indipendenti, quindi il compilatore semplicemente non può sapere se una classe è sottoclassata in un altro modulo, perché non guarda mai più di un modulo. (Dopo tutto, potresti compilare un modulo contro l'interfaccia di qualche altro modulo senza che quel modulo sia già presente sul tuo sistema!) Ecco perché sealed richiede che tutte le sottoclassi siano definite nella stessa unità di compilazione.

Questo è anche uno dei motivi per cui le JVM possono competere in modo così favorevole con i compilatori C ++: i compilatori C ++ sono tipicamente compilatori statici, quindi non possono in generale capire se un metodo è sovrascritto o meno, e quindi non possono in linea . JVMs OTOH, in genere sono compilatori dinamici, non hanno bisogno di eseguire CHA per capire se un metodo è sovrascritto o meno, possono solo guardare la gerarchia di classi in fase di runtime. E anche se in un momento successivo nell'esecuzione del programma arriva una nuova sottoclasse che prima non c'era, non è un grosso problema, basta ricompilare quel pezzo di codice senza inlining.

Nota: tutto ciò si applica solo all'interno di Scala. La JVM non ha alcuna nozione di sealed , quindi è perfettamente possibile suddividere% delle classi% co_de da un altro linguaggio JVM, poiché non c'è modo di comunicarlo ad un'altra lingua. La proprietà sealed è registrata nell'annotazione sealed , ma i compilatori di altre lingue non prendono in considerazione queste annotazioni, ovviamente.

    
risposta data 18.12.2014 - 14:28
fonte
3

È possibile essere fatto (almeno per tutte le classi conosciute al momento della compilazione), è solo costoso. Distruggerebbe completamente la compilazione incrementale, poiché tutto ciò che contiene una corrispondenza di pattern dovrebbe essere ricompilato in modo efficace ogni volta che viene modificato un altro file.

E cosa stai comprando? È un odore di codice scrivere corrispondenze di pattern che devono cambiare frequentemente quando viene aggiunta una nuova classe derivata. È una violazione del principio aperto / chiuso . Usa l'ereditarietà correttamente e non dovrai scrivere quei tipi di corrispondenze di pattern. E sì, il principio aperto / chiuso si applica anche ai linguaggi funzionali senza ereditarietà basata sulla classe. Infatti, tra funzioni come classi di tipi, metodi multimodali e semplici funzioni di ordine superiore, i linguaggi funzionali rendono l'estensione senza modifiche molto più semplice.

    
risposta data 18.12.2014 - 14:44
fonte

Leggi altre domande sui tag