Twierdzenie to przez Aleks Bromfield stwierdza:
Prawie każdy język ze statycznym systemem typów ma również dynamiczny system typów. Oprócz C nie mogę wymyślić wyjątku
Czy jest to uzasadnione roszczenie? Rozumiem, że dzięki klasom refleksyjnym lub ładującym w środowisku uruchomieniowym Java jest trochę podobna - ale czy ten pomysł „stopniowego pisania” można rozszerzyć na wiele języków?
languages
dynamic-typing
static-typing
Sokole Oko
źródło
źródło
Odpowiedzi:
Oryginalny tweeter tutaj. :)
Przede wszystkim jestem nieco rozbawiony / zszokowany tym, że mój tweet jest traktowany tak poważnie! Gdybym wiedział, że będzie to tak szeroko rozpowszechnione, spędziłbym ponad 30 sekund na pisaniu tego!
Thiago Silva słusznie zauważa, że „statyczny” i „dynamiczny” dokładniej opisują sprawdzanie typu , a nie systemy typu . W rzeczywistości stwierdzenie, że język jest wpisywany statycznie lub dynamicznie, jest niedokładne. Język ma raczej system typów, a implementacja tego języka może wymusić system typów przy użyciu sprawdzania statycznego lub dynamicznego, albo jedno i drugie, lub oba (choć nie byłaby to bardzo atrakcyjna implementacja językowa!).
Tak się składa, że istnieją pewne systemy typów (lub cechy systemów typów), które są bardziej podatne na sprawdzanie statyczne, i są pewne systemy typów (lub cechy systemów typów), które są bardziej podatne na sprawdzanie dynamiczne. Na przykład, jeśli twój język pozwala ci określić w tekście programu, że określona wartość musi zawsze być tablicą liczb całkowitych, to dość rozsądnie jest napisać statyczny moduł sprawdzający, aby zweryfikować tę właściwość. I odwrotnie, jeśli twój język ma podtypy i jeśli pozwala na downcasting, to dość łatwo jest sprawdzić poprawność downcastu w czasie wykonywania, ale niezwykle trudno to zrobić w czasie kompilacji.
To, co naprawdę rozumiem przez mój tweet, to po prostu to, że zdecydowana większość implementacji językowych wykonuje pewną część dynamicznego sprawdzania typów. Lub, równoważnie, ogromna większość języków ma pewne funkcje, które są trudne (jeśli nie niemożliwe) do sprawdzenia statycznego. Przykładem jest downcasting. Inne przykłady obejmują przepełnienie arytmetyczne, sprawdzanie granic tablic i sprawdzanie wartości NULL. Niektóre z nich można sprawdzić statycznie w niektórych okolicznościach, ale ogólnie rzecz biorąc, trudno byłoby znaleźć implementację języka, która nie wykonuje żadnej kontroli w czasie wykonywania.
to nie jest zła rzecz. To tylko spostrzeżenie, że istnieje wiele interesujących właściwości, które chcielibyśmy egzekwować w naszych językach i że tak naprawdę nie wiemy, jak to sprawdzić statycznie. Jest to przypomnienie, że rozróżnienia, takie jak „typy statyczne” w porównaniu z „typami dynamicznymi”, nie są tak wyraźne, jak niektórzy chcieliby, by ci się wydawało. :)
Ostatnia uwaga: terminy „silny” i „słaby” nie są tak naprawdę używane w społeczności badaczy języków programowania i nie mają tak naprawdę spójnego znaczenia. Ogólnie stwierdziłem, że kiedy ktoś mówi, że język ma „mocne pisanie”, a jakiś inny język ma „słabe pisanie”, to tak naprawdę mówi, że ich ulubiony język (ten z „mocnym pisaniem”) uniemożliwia mu popełniając jakiś błąd, że inny język (ten z „słabym pisaniem”) nie - lub odwrotnie, że ich ulubiony język (ten z „słabym pisaniem”) pozwala im zrobić coś fajnego, że drugi język ( jeden z „silnym pisaniem”) nie.
źródło
No tak. Możesz mieć torby własności w dowolnym statycznie pisanym języku. Składnia będzie okropna, a jednocześnie zyskasz wszystkie wady dynamicznie typowanego systemu. Tak naprawdę nie ma żadnej przewagi, chyba że kompilator pozwala na użycie ładniejszej składni, co
dynamic
robi coś w stylu C # .Możesz również zrobić to dość łatwo w C.
W odpowiedzi na inne odpowiedzi: Myślę, że ludzie mylą pisanie statyczne / dynamiczne z pisaniem mocnym / słabym. Wpisywanie dynamiczne polega na możliwości zmiany struktury danych w czasie wykonywania, a na wykorzystaniu kodu, który odpowiada potrzebom kodu. Nazywa się to pisaniem kaczek .
Wspominanie o refleksji nie mówi całej historii, ponieważ refleksja nie pozwala na zmianę istniejącej struktury danych. Nie możesz dodać nowego pola do klasy lub struktury w języku C, C ++, Java lub C #. W językach dynamicznych dodawanie nowych pól lub atrybutów do istniejących klas jest nie tylko możliwe, ale w rzeczywistości dość powszechne.
Na przykład spójrz na Cython , kompilator Python-to-C. Tworzy statyczny kod C, ale system typów wciąż zachowuje swój dynamiczny charakter. C jest językiem o typie statycznym, ale jest w stanie obsługiwać dynamiczne pisanie z języka Python.
źródło
ExpandoObject
, chociaż jest to proces opt-in, w przeciwieństwie do JavaScript lub Ruby. Mimo to podjąłeś bardzo ważną kwestię, którą jest pisanie kaczek (co 99% programistów tak naprawdę znaczy, gdy mówią „dynamicznie pisane”) i refleksja to wcale nie to samo.True
, aby powiedzieć „ten zwariowany obiekt jest instancją klasy, którą definiuję”). OCaml ma tę funkcję, o ile rozumiem, ale tak naprawdę nie wiem.Języki dynamiczne to języki statyczne . To, co jest powszechnie nazywane „pisaniem dynamicznym”, jest tak naprawdę szczególnym przypadkiem pisania statycznego - przypadek, w którym ograniczyłeś się do posiadania tylko jednego typu. Jako eksperyment myślowy wyobraź sobie pisanie programu w Javie lub C # przy użyciu tylko
Object
zmiennych / pól / parametrów i rzucanie w dół bezpośrednio przed wywołaniem dowolnej metody. Bardziej dokładne byłoby nazywanie języków takich jak Python lub JavaScript „unityped”. (To twierdzenie prawdopodobnie dezorientuje / przeszkadza wielu osobom, biorąc pod uwagę, że taki program Java lub C # użyłby wielu podtypów, ale dzieje się tak, ponieważ przeciętny język OOP łączy typy i klasy. Przeczytaj więcej postów na blogu).Zauważ, że nawet C ma „dynamiczne” pisanie - możesz rzucić dowolny wskaźnik na
void
(i jeśli pamięć mi to służychar
) wskaźnik iz powrotem. Zauważ też, że nie ma tam sprawdzania czasu wykonywania; jeśli się pomylisz, ciesz się swoim niezdefiniowanym zachowaniem!źródło
String foo = (String) bar
że to nie znaczy, żebar
tak naprawdę jestString
. Możesz to wiedzieć tylko na pewno w czasie wykonywania, więc nie widzę, jak obsada jest wykonywana „statycznie”.dynamic
obiektu, aby to zrobić. Jeśli spróbujesz dodać właściwość doobject
... cóż, nie możesz.Różnica między statycznych i dynamicznych typowania jest gdy typ wartości jest sprawdzana: kompilacji czas pracy w porównaniu. W językach, w których wartości niosą ze sobą swój typ (np. Obiekty Java), zawsze możesz skorzystać z pisania dynamicznego, nawet jeśli język rzeczywiście woli pisać statycznie. Oto przykład w Javie z dynamicznie wpisywaną metodą:
Zwróć uwagę, w jaki sposób sprawdzany jest typ każdego elementu w czasie wykonywania. Równoważna metoda o typie statycznym to:
W C wartości (a konkretnie wskaźniki) nie zachowują swojego typu podczas działania - każdy wskaźnik jest równoważny a
void *
. Zamiast tego zmienne i wyrażenia mają typ. Aby osiągnąć dynamiczne pisanie, musisz sam nosić informacje o typie (np. Jako pole w strukturze).źródło
frobnicate
tutaj wywołać tej metody bez uprzedniej wiedzy o niejSpecificType
.dynamic
Słowem kluczowym). Zrównanie czasu statycznego z czasem kompilacji i dynamicznego ze środowiskiem wykonawczym przeważnie powoduje zamulenie wód.[1,2].Add([3,4])
wydajność[1,2,3,4]
,[1,2,[3,4]]
albo[4,6]
?Add
metody na tablicy, która akceptuje tablicę, ponieważ taka metoda byłaby niejednoznaczna. Pisanie kaczką nie usprawiedliwia pisania zrozumiałych typów i funkcji.Pisanie statyczne vs. dynamiczne zasadniczo odnosi się do sposobu sprawdzania typów. Wpisywanie statyczne oznacza, że weryfikacja typów różnych zmiennych lub wyrażeń jest sprawdzana na podstawie rzeczywistego kodu (zwykle przez kompilator), natomiast w systemie typów dynamicznych weryfikacja ta jest wykonywana tylko w czasie wykonywania przez środowisko wykonawcze.
Uważam, że tekst odnosi się do tego, że nawet jeśli typy są faktycznie sprawdzane statycznie, są one również sprawdzane w czasie wykonywania, tj. Dynamicznie. Poprawnie wspomniałeś Java Reflection; odbicie odbywa się tylko w czasie wykonywania, a środowisko Java Runtime Environment (JVM) faktycznie sprawdza typ, gdy używane jest odbicie, co w zasadzie oznacza dynamiczne sprawdzanie typu.
źródło
Wykluczenie jest błędne: C ma również ważny dynamiczny system typów. Po prostu tego nie sprawdza („C jest mocno wpisany, słabo zaznaczony”). Na przykład traktowanie struktury jako
double
(reinternpret_cast
stylu) daje niezdefiniowane zachowanie - błąd typu dynamicznego.źródło