2015-03-21 17 views
5

Sto leggendo "The D Programming Language" di Andrei Alexandrescu e una frase mi ha sconcertato. Consideriamo tale codice (p.138):Cosa c'è di sbagliato nel tipo di modello e nella conversione di tipo implicito?

T[] find(T)(T[] haystack, T needle) { 
    while (haystack.length > 0 && haystack[0] != needle) { 
     haystack = haystack[1 .. $]; 
    } 
    return haystack; 
} 

e chiamare (p.140):

double[] a = [ 1.0, 2.5, 2.0, 3.4 ]; 
a = find(a, 2); // Error! ' find(double[], int)' undefined 

Spiegazione (paragrafo sotto il codice):

Se strabismo abbastanza duro , vediamo che l'intento del chiamante in questo caso era di avere T = double e beneficiare della bella conversione implicita da int a double. Tuttavia, avere il tentativo linguistico combinatorio allo stesso tempo di conversioni implicite e deduzione di tipo è una proposizione azzardata nel caso generale, quindi D non tenta di fare tutto questo.

Sono perplesso perché un linguaggio come C# cerca di dedurre il tipo - se non può farlo, l'utente ottiene errore, ma se può, beh, funziona. C# vive con lui per diversi anni e non ho sentito nessuna storia di come questa caratteristica abbia rovinato la giornata di qualcuno.

E così le mie domande sono queste: quali pericoli sono coinvolti con i tipi di inferenza come nell'esempio sopra?

Vedo solo vantaggi, è facile scrivere funzioni generiche ed è facile chiamarlo. Altrimenti dovresti introdurre più parametri nella classe/funzione generica e scrivere vincoli speciali che esprimono le conversioni permesse solo per motivi di inferenza.

+4

Quanto sopra sembra funzionare correttamente in 'dmd 2.066'. Immagino che abbiano deciso che la proposizione non era "rischiosa" come pensavano. – rcorre

+5

Questa funzione è stata introdotta circa un anno fa in questo PR: https://github.com/D-Programming-Language/dmd/pull/3353 –

risposta

1

La prima cosa da notare è che non dice che c'è un problema con il tipo di deduzione, è che c'è un problema con il tipo di detrazione e conversione implicita allo stesso tempo.

Quindi, se si dispone di:

a = find(a, 2.0); 

allora è felice di dedurre double come tipo.

E se digitati esplicitamente per il doppio, è felice di dedurre che 2 deve essere inoltrato implicitamente a 2.0.

Quello che non sta per fare è entrambi allo stesso tempo.

Ora, C# lo fa. E penso che per la maggior parte sono d'accordo con te, è generalmente conveniente e generalmente funziona abbastanza bene.

È vero, al tempo stesso, che può essere fonte di confusione, soprattutto nei casi in cui porta a più di un sovraccarico altrettanto ragionevole.

Why type inference and implicit operator is not working in the following situations? e Why does Assert.AreEqual on custom struct with implicit conversion operator fail? sono entrambe domande sul motivo per cui una particolare combinazione di conversione implicita e tipo di inferenza non ha funzionato.

Unexpected effect of implicit cast on delegate type inference ha altri fattori, ma si rifiuta nuovamente di considerare il metodo nell'elenco di possibili corrispondenze perché il tipo di argomento non corrisponde significa che il problema non si è verificato.

Sarebbero entrambi molto più semplici se la risposta fosse sempre "perché si sta facendo la conversione implicita e l'inferenza di tipo allo stesso tempo, e questo non è supportato". Quale sarebbe la risposta con D.

D'altra parte, tuttavia, tali problemi non sorgono così spesso, quindi preferisco ancora la decisione di design C# per consentire entrambi, ma che ci sono alcuni problemi significa che è ancora una ragionevole decisione progettuale di non permetterle.

Problemi correlati