2010-09-24 12 views
12

Nie mam dużego doświadczenia ze statycznie napisanymi językami (obecnie uczę się Scala i kocham to!), Ale jedną rzecz, którą zauważyłem jest to, że nigdy nie wydają się mieć czegoś takiego jak metoda method_missing Rubiego czy metoda onMissingMethod firmy ColdFusion. Czy istnieje pewne nieodłączne ograniczenie w statycznie napisanych językach, które uniemożliwiają lub utrudniają to?Co sprawia, że ​​język statycznie napisany nie ma czegoś takiego jak metoda_racjonowania Rubiego?

+0

Dla przykładu statycznie napisanego języka, który * ma * ma coś takiego wbudowanego, spójrz na [opDispatch w D] (http://www.digitalmars.com/d/2.0/operatoroverloading.html #Wysyłka). 'opDispatch' jest metodą szablonową, która przekazuje nazwę metody i typy parametrów w czasie kompilacji, więc możesz użyć metaprogramowania, aby określić sposób" uruchomienia "brakującej metody. Oczywiście wszystko jest nadal statycznie rozwiązane przez kompilator. [Powiązane pytanie SO] (http://stackoverflow.com/questions/3098242/fast-vector-struct-that-allows-i-and-xyz-operations-in-d). – shambulator

Odpowiedz

21

Z pewnością można by dodać mechanizm ich obsługi, ale jest to sprzeczne z tym, co pisze się statycznie: Ustalenie czasu kompilacji, w którym program jest wolny od błędów typu.

Uzupełnienie

Scala 2.9 wprowadzono opcję eksperymentalne umożliwiające tego rodzaju dynamicznej obsługi dostępów do typów w sposób, który inaczej nie uda statycznej kontroli typów. Został udoskonalony i wykonany jako nieeksperymentalny w wersji 2.10, choć nadal jest kontrolowany przez domyślną flagę funkcji wyłączania. Możesz przeczytać o tym w dokumencie SIP 17. Zobacz SIP 18, aby uzyskać wyjaśnienie "modularyzacji" i flag funkcji w Scali 2.10.

+5

Refleksja API również to narusza, ale są one obecne i bardzo często używane w większości współczesnych języków statycznych –

+0

co Randall powiedział, że jest poprawne. Dla lepszego lub gorszego "historycznie", był to duży podział na "czas kompilacji", a nie na "kompilację". Powiedziawszy, niektóre nowsze języki są bliżej do wypełnienia luki (pojawia się scala, która moim zdaniem ma REPL). – rogerdpack

+0

@rogerdpack: Scala z pewnością ma REPL, chociaż nie uważam tego za aspekt bycia "dynamicznym", tylko wielką wygodę przy pracy z językiem. –

1

W językach wpisanych statycznie funkcje członkowskie są wywoływane bezpośrednio. Jeśli kompilator nie może dowiedzieć się, która funkcja elementu wywoła, program się nie skompiluje. Wywołanie metody jest w tym sensie statyczne.

W językach wpisanych dynamicznie funkcje członkowskie nie są wywoływane bezpośrednio. Zamiast tego kod wywołujący wysyła wiadomość do obiektu, a następnie język wykonawczy określa, co zrobić z tym komunikatem. Na przykład środowisko wykonawcze skanuje obiekt w poszukiwaniu metody o tej samej nazwie, a następnie skanuje obiekt pod kątem metody o nazwie method_missing. Inwokacja metod jest w tym sensie dynamiczna.

C# 4 łączy statyczne pisanie z dynamicznym typowaniem. Zmienna może mieć typ kompilacji: dynamic. Wszelkie wywołania metody na tej zmiennej będą obsługiwane tak jak w językach z dynamicznym typowaniem. Wszelkie wywołania metod na zmiennych o typach statycznych będą obsługiwane tak, jak w językach statycznie pisanych.

# 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

Miksujesz rzeczy. Dyspozycja dynamiczna istnieje w każdym języku OO ze statycznie wpisanym typem. I tylko niektóre dynamicznie pisane języki wykorzystują model przekazywania wiadomości jako pionierski w Smalltalk. Python na przykład nie używa przekazywania komunikatów (zamiast tego, "obj.method (args)" tłumaczy się na "uzyskaj funkcję, do której wskazuje element' method' obiektu "obj", a następnie wywołaj go za pomocą 'obj' jako pierwszego argumentu i 'args'"). – delnan

+0

'var' nie ma nic wspólnego z dynamicznym pisaniem. Powoduje, że kompilator wyprowadza statyczny typ zmiennej z przypisanej mu wartości. –

+0

Dziękuję za poprawioną poprawkę. – yfeldblum

1

Wystarczy do dalszego stanowisko Randalla, jest możliwe, ale powodem jest to sprzeczne statycznego paradygmatu jest to, że poza „dynamicznej wysyłki”. Dynamiczna wysyłka pozwala na wysłanie do funkcji, która jest dynamicznie związana ze znanym statycznym fragmentem kodu. tj. kompilator ustawia wysyłkę, która jest deterministycznie wykonywana w środowisku wykonawczym, z jej perspektywy.

To, co wywołuje method_missing, polega zasadniczo na "złapaniu wszystkiego", gdzie zdecydujesz, co zrobić na podstawie nazwy metody za pomocą instrukcji switch lub czegoś podobnego (co na pewno wiesz). Tak więc kompilator nie ma pojęcia, co się tutaj stanie. Powiedzmy, że kompilator zrobił coś takiego:

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" 
} 

Następnie trzeba dostarczyć method_missing takiego:

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 ... 
} 

wyjściowa kompilator do was posyłam „arbitralne” (czyli nie wiadomo, w czasie kompilacji) argumenty arbitralne typy, z intendedFunctionName, którego możesz nie uwzględniać ... no cóż, to nie jest bardzo bezpieczne, a Scala ma być statycznie bezpiecznym językiem.

Tak, jest to wykonalne, ale nie w duchu języka statycznego. Jeśli naprawdę chcesz tego rodzaju elastyczność, programowanie poliglota jest prawdopodobnie twoim przyjacielem.

Uwaga: Cel C nie jest typowo statyczny. Istnieje mechanizm uruchomieniowy, na którym wykonuje się kod, a system dynamicznego pisania nie pozwala na usunięcie kodu lub wstawienie go w stylu C/C++.

+0

"Z prośbą o kompilator, aby wysyłać ci" arbitralne "(tj. Nieznane w czasie kompilacji) argumenty o arbitralnych typach" i "niezbyt bezpieczne" brzmią tak, jak C varargs. :) – bk1e

0

Objective-C ma "method_missing" (konkretnie, forwardInvocation i methodSignatureForSelector) i jest prawdopodobnie napisane statycznie. Działa to, ponieważ traktuje statyczne błędy typu jako ostrzeżenia, a nie błędy podczas kompilacji, ponieważ wysyłanie metod odbywa się w środowisku wykonawczym w znacznie większym zakresie niż coś podobnego do wirtualnych metod w C++ (i dlatego można mieć "method_missing").

2

Scala w wersji 2.9 wprowadza tę funkcjonalność poprzez cechę Dynamic(). Klasy, które rozciągają się na Dynamic, uzyskują magiczną metodę, która jest analogiczna do metody Ruby z . Od wersji Scala 2.9 opcja -Xexperimental musi być włączona, aby można było używać Dynamic.

Powiązane problemy