2010-09-24 19 views
12

Non ho molta esperienza con i linguaggi tipizzati staticamente (attualmente sto imparando Scala e lo adoro!) Ma una cosa che ho notato è che non sembrano mai avere qualcosa come il metodo_missing di Ruby o il metodo onMissing di ColdFusion. Esiste qualche limitazione intrinseca in linguaggi tipizzati staticamente che impediscono o rendono difficile?Cosa impedisce ad un linguaggio tipizzato staticamente di avere qualcosa come il metodo_missing di Ruby?

+0

Per un esempio di un linguaggio tipizzato staticamente che * ha * ha qualcosa di simile a questo built-in, date un'occhiata a [opDispatch in D] (http://www.digitalmars.com/d/2.0/operatoroverloading.html #Spedizione). 'opDispatch' è un metodo template che ha passato il nome del metodo e i tipi di parametro al momento della compilazione, quindi puoi usare metaprogramming per determinare come" eseguire "il metodo mancante. Naturalmente, tutto è ancora risolto staticamente dal compilatore. [Questione SO correlata] (http://stackoverflow.com/questions/3098242/fast-vector-struct-that-allows-i-and-xyz-operations-in-d). Le API di riflessione – shambulator

risposta

21

È possibile aggiungere un meccanismo per gestirli, ma è in contrasto con la tipizzazione statica: determinazione del tempo di compilazione in base alla quale il programma è privo di errori di tipo.

addendum

Scala 2.9 introdotto un'opzione sperimentale che consente questo tipo di gestione dinamica degli accessi ai tipi in modo che altrimenti sicuro controllo di tipo statico. È stato perfezionato e reso non sperimentale in 2.10, sebbene sia ancora controllato da un flag di funzionalità di disabilitazione predefinita. Puoi leggere a riguardo nel documento SIP 17. Vedere SIP 18 per una spiegazione della "modularizzazione" di Scala 2.10 e dei flag di funzionalità.

+5

violano anche questo, ma sono presenti e molto utilizzate nella maggior parte dei moderni linguaggi statici –

+0

ciò che Randall ha detto è corretto. Nel bene e nel male, "storicamente" è stato un grande divario per "tempo di compilazione" anziché no. Detto questo, alcuni linguaggi più recenti si avvicinano a colmare il divario (scala viene in mente, che credo abbia un REPL). – rogerdpack

+0

@rogerdpack: Scala ha sicuramente un REPL, anche se non lo considero un aspetto dell'essere "dinamico", solo un'enorme comodità quando si lavora con la lingua. –

1

In lingue con tipizzazione statica, le funzioni membro vengono richiamate direttamente. Se il compilatore non riesce a capire quale funzione membro invocare, il programma non verrà compilato. L'invocazione del metodo è, in questo senso, statica.

Nelle lingue digitate dinamicamente, le funzioni membro non vengono richiamate direttamente. Piuttosto, chiamare il codice invia un messaggio a un oggetto e quindi il runtime della lingua calcola cosa fare con quel messaggio. Ad esempio, il runtime esegue la scansione dell'oggetto per un metodo con lo stesso nome, quindi esegue la scansione dell'oggetto per un metodo con il nome method_missing. L'invocazione del metodo è, in questo senso, dinamica.

C# 4 combina la digitazione statica con la digitazione dinamica. Una variabile può avere un tipo in fase di compilazione di dynamic. Qualsiasi invocazione di metodi su questa variabile verrà gestita come nelle lingue digitate dinamicamente. Eventuali invocazioni di metodi su variabili con tipi statici verranno gestite come in lingue tipizzate staticamente.

# static invocation, bound at compile time by the compiler 
var s = 6; 
s.ToString(); 

# dynamic invocation, handled at runtime by the CLR 
dynamic d = 6; 
d.ToString(); 
+2

Stai mescolando cose. Dispatch dinamico esiste in circa ogni linguaggio OO tipizzato staticamente. E solo alcuni linguaggi tipizzati dinamicamente utilizzano il modello di trasmissione dei messaggi come pioniere di Smalltalk. Python ad esempio non usa il message passing (invece, 'obj.method (args)' si traduce in "ottenere la funzione a cui punta il membro' method' di 'obj', quindi chiamarla con' obj' come primo argomento e 'args'"). – delnan

+0

'var' non ha nulla a che fare con la digitazione dinamica. Fa in modo che il compilatore deduca il tipo statico della variabile dal valore ad esso assegnato. –

+0

Grazie per la correzione, risolto. – yfeldblum

1

Giusto per ulteriori post di Randall, è possibile, ma la ragione va contro il paradigma statico è che è al di là di "spedizione dinamica". Il dispatch dinamico ti consente di inviare a una funzione legata dinamicamente a un pezzo di codice statico noto. cioè il compilatore imposta il dispatch che viene eseguito in modo deterministico in fase di runtime, dal suo punto di vista.

Che cosa fa la chiamata method_missing, è essenzialmente fare un "catch all" dove si decide cosa fare in base al nome del metodo utilizzando un'istruzione switch o qualcosa di equivalente (che sono sicuro che tu sappia). Quindi, il compilatore non ha idea di cosa succederà qui. Diciamo che il compilatore ha fatto qualcosa di simile:

if (function is known at compile time) 
{ 
    provide static call or dynamic call to "some" derivation 
} 
else 
{ 
    bind the function call to obj.method_missing(...) and pass in the "details" 
} 

Poi è necessario fornire method_missing in questo modo:

def method_missing(intendedFunctionName, arguments) 
{ 
    if (intendedFunctionName is "X") 
    { 
    X may not need arguments, so just do something 
    } 
    else if (intendedFunctionName is "Y") 
    { 
    Y expects 5 arguments of varying types 
    Throw exception if there isn't the right number or types 
    } 
    ... etc ... 
} 

Chiedendo il compilatore per l'invio di "arbitrari" (cioè non noto al momento della compilazione) argomenti di tipi arbitrari, con un intendedFunctionName che potresti non essere responsabile ... beh, non è molto sicuro, e Scala è inteso per essere un linguaggio staticamente sicuro.

Sì, è fattibile ma non nello spirito di un linguaggio statico. Se vuoi davvero quel tipo di flessibilità, la programmazione poliglotta è probabilmente tua amica.

Nota: Objective-C non è tipizzato in modo statico. Esiste un motore di runtime su cui il codice viene eseguito e il sistema di battitura dinamico non consente il stripping del codice o l'inclusione come C/C++.

+0

"Chiedere al compilatore di inviarti" arbitrari "(cioè non noto in fase di compilazione) argomenti di tipi arbitrari" e "non molto sicuri" suonano proprio come C varargs. :) – bk1e

0

Objective-C ha "method_missing" (in particolare, forwardInvocation e methodSignatureForSelector) ed è probabilmente tipizzato staticamente. Questo funziona perché tratterà gli errori di tipo statico come avvertenze piuttosto che come errori in fase di compilazione, poiché la distribuzione dei metodi avviene in fase di esecuzione in misura molto maggiore rispetto a metodi virtuali in C++ (ed è per questo che è possibile eseguire "method_missing").

2

Scala versione 2.9 introduce questa funzionalità tramite il tratto Dynamic (scaladoc). Le classi che estendono lo Dynamic ottengono il metodo magico applyDynamic(methodName, args), che è analogo a quello di Ruby method_missing. A partire da Scala 2.9, l'opzione -Xexperimental deve essere abilitata per utilizzare Dynamic.