Dopo aver riflettuto su questo argomento, penso che possa essere provato che non è possibile affrontare la ricercabilità interamente con il tempo di compilazione tipo di controllo.
-
In Linux / Unix ci sono cose chiamate "named socket" che esistono nel file system e possono essere aperte allo stesso modo degli altri oggetti nel file system. Il problema è che non sono ricercabili. E ci sono "file dispositivo" che hanno la stessa proprietà; per esempio. "/ dev / tty" o "/ dev / null".
-
Una libreria IO deve essere in grado di creare un flusso di input o di output per un oggetto usando un nome file o percorso fornito come stringa; vale a dire un valore di runtime. (Se non puoi farlo, la lingua ha "utilità limitata".)
-
Il metodo "aperto" deve quindi essere in grado di affrontare i casi in cui potrebbe essere chiesto di aprire un oggetto ricercabile o un oggetto non ricercabile ... e che non saprà quale è il caso fino a quando non lo ha provato.
-
Ciò significa che anche se si dovesse progettare un set di API che distingue tra flussi cercabili e non ricercabili, sarebbe comunque necessario eseguire un test di runtime per determinare se un file specifico potrebbe > em> essere aperto come flusso ricercabile (o non ricercabile).
In breve, non è possibile gestirlo interamente tramite tipizzazione statica.
Aggiorna
Mat Fennwick ha commentato così:
Perhaps I'm missing something, but it seems to me that your example could be handled with an algebraic sum type, à la Haskell. Is that not the case?
Sì, penso che potresti esprimere diversi tipi di stream usando i tipi di somma algebrica. Ma non vedo come questo ti darà un errore di compilazione se tu:
- apri uno stream in base a un nome percorso, quindi
- prova a fare una ricerca su un flusso non ricercabile.
Finirai per dover fare un switch
per discriminare i casi cercabili e non ricercabili e affrontare la possibilità che tu abbia il tipo di flusso sbagliato.
Ora potrebbe progettare le API per ridurre al minimo il controllo runtime. Ma la mia sensazione è che ciò ha un costo. E il costo è che le classi che usano le API diventano più complicate. Ad esempio, ogni volta che si passa a un oggetto flusso è necessario pensare se è necessario dichiarare il metodo per richiedere un parametro di flusso cercabile o non ricercabile. (E non puoi semplicemente dire "entrambi" tutto il tempo e usare un supertipo comune ... perché allora hai bisogno di un typecast nel punto in cui il flusso deve essere ricercabile e il tuo compilatore non può più rilevare il vero problema. )
L'altro problema con la mappatura (efficace) delle proprietà di runtime per compilare i tipi di tempo / interfacce è che diventa complicato quando ne hai più; per esempio. immagina se tu avessi tipi / interfacce per ricerca, leggibilità, scrivibilità, deletabilità e così via. Si finisce con un'esplosione combinatoria delle classi foglia.
Infine, se fosse una buona idea, avresti pensato che qualcuno avrebbe provato, mostrato che fosse una buona idea e convinto qualcuno ad aggiungerlo a un linguaggio di programmazione mainstream. AFAIK, l'ultimo passo non è successo. OK, non è una prova che non funzionerà ... ma l'assenza è abbastanza convincente.