Języki typu dynamicznego a języki typu statycznego

205

Jakie są zalety i ograniczenia języków typu dynamicznego w porównaniu do języków typu statycznego?

Zobacz także : co z zamiłowaniem do dynamicznych języków (o wiele bardziej argumentacyjny wątek ...)

CVS
źródło
10
To pytanie jest zbyt subiektywne.
Jason Dagit
7
Nie nazwałbym tego subiektywnym, ale przynętą ognistą. Ale są pewne obiektywne fakty na ten temat.
Vinko Vrsalovic
2
Uzgodniony: zbyt subiektywny. Interesujące jest porównanie i skontrastowanie obu podejść, ale niebezpiecznie balansuje na krawędzi apokalipsy forum.
Daniel Spiewak
17
Języki dynamiczne świetnie nadają się do szybkiego opracowywania aplikacji demonstracyjnych / wyrzucanych, ponieważ jeśli popełnisz literówkę, której to obchodzi, strona internetowa nadal się ładuje, możesz mieć tu lub tam kilka elementów danych. Nie wyobrażam sobie żadnej innej sytuacji, w której możliwość błędnego wpisania zmiennych bez otrzymania błędu kompilatora jest postrzegana jako „zaleta”.
Alex R
4
Taki błąd zazwyczaj powoduje zatrzymanie JavaScript, co uważam za bardzo dobrą rzecz. Przynajmniej spowodowałoby to błędy, które również uważam za wartościowe. Z jakiegoś powodu zawsze jest to facet ze statycznego paradygmatu pisania, który chce zakopać swoje błędy javascript za pomocą pustych instrukcji try / catch. To było coś z mojego doświadczenia. Co to jest? Niezależnie od tego, to nie jest tak, że nie otrzymujemy opinii, kiedy uruchamiamy nasz kod.
Erik Reppen

Odpowiedzi:

139

Zdolność interpretera do wnioskowania o konwersjach typów i czcionek przyspiesza czas programowania, ale może także wywoływać awarie środowiska wykonawczego, których po prostu nie można uzyskać w języku o typie statycznym, w którym można je złapać w czasie kompilacji. Ale który z nich jest lepszy (a nawet jeśli to zawsze prawda) jest obecnie gorąco dyskutowany w społeczności (i od dłuższego czasu).

Dobre podejście do tej kwestii pochodzi z pisania statycznego tam, gdzie jest to możliwe, pisania dynamicznego w razie potrzeby: koniec zimnej wojny między językami programowania autorstwa Erika Meijera i Petera Draytona z firmy Microsoft:

Zwolennicy pisania statycznego twierdzą, że zalety pisania statycznego obejmują wcześniejsze wykrywanie błędów programistycznych (np. Zapobieganie dodawaniu liczby całkowitej do wartości logicznej), lepszą dokumentację w postaci podpisów typów (np. Uwzględnianie liczby i typów argumentów podczas rozwiązywania nazw), więcej możliwości optymalizacji kompilatora (np. zastępowanie połączeń wirtualnych wywołaniami bezpośrednimi, gdy dokładny typ odbiornika jest znany statycznie), zwiększona wydajność środowiska wykonawczego (np. nie wszystkie wartości muszą zawierać typ dynamiczny) oraz lepsze doświadczenie programisty w czasie projektowania (np. znajomość rodzaj odbiornika, IDE może prezentować menu rozwijane wszystkich odpowiednich członków). Fanatycy pisania statycznego próbują przekonać nas, że „dobrze napisane programy nie mogą się nie udać”. Chociaż z pewnością brzmi to imponująco, jest to raczej próżne stwierdzenie. Statyczne sprawdzanie typu jest abstrakcyjną zachowaniem środowiska wykonawczego programu w czasie kompilacji, a zatem jest koniecznie tylko częściowo solidne i niekompletne. Oznacza to, że programy mogą nadal popsuć się z powodu właściwości, które nie są śledzone przez moduł sprawdzania typu, oraz że istnieją programy, które nie mogą się pomylić, mimo że nie mogą się pomylić. Impuls powodujący, że typowanie statyczne jest mniej częściowe i bardziej kompletne, powoduje, że systemy typów stają się nadmiernie skomplikowane i egzotyczne, o czym świadczą pojęcia takie jak „typy fantomowe” [11] i „chwiejne typy” [10]. To tak, jakby próbować przebiec maraton z piłką i łańcuchem przywiązanym do nogi i triumfalnie krzyczeć, że prawie udało ci się, mimo że wyskoczyłeś po pierwszej mili. Statyczne sprawdzanie typu jest abstrakcyjną zachowaniem środowiska wykonawczego programu w czasie kompilacji, a zatem jest koniecznie tylko częściowo solidne i niekompletne. Oznacza to, że programy mogą nadal popsuć się z powodu właściwości, które nie są śledzone przez moduł sprawdzania typu, oraz że istnieją programy, które nie mogą się pomylić, mimo że nie mogą się pomylić. Impuls powodujący, że typowanie statyczne jest mniej częściowe i bardziej kompletne, powoduje, że systemy typów stają się nadmiernie skomplikowane i egzotyczne, o czym świadczą pojęcia takie jak „typy fantomowe” [11] i „chwiejne typy” [10]. To tak, jakby próbować przebiec maraton z piłką i łańcuchem przywiązanym do nogi i triumfalnie krzyczeć, że prawie udało ci się, mimo że wyskoczyłeś po pierwszej mili. Statyczne sprawdzanie typu jest abstrakcyjną zachowaniem środowiska wykonawczego programu w czasie kompilacji, a zatem jest koniecznie tylko częściowo solidne i niekompletne. Oznacza to, że programy mogą nadal popsuć się z powodu właściwości, które nie są śledzone przez moduł sprawdzania typu, oraz że istnieją programy, które nie mogą się pomylić, chociaż nie mogą się pomylić. Impuls powodujący, że typowanie statyczne jest mniej częściowe i bardziej kompletne, powoduje, że systemy typów stają się nadmiernie skomplikowane i egzotyczne, o czym świadczą pojęcia takie jak „typy fantomowe” [11] i „chwiejne typy” [10]. To tak, jakby próbować przebiec maraton z piłką i łańcuchem przywiązanym do nogi i triumfalnie krzyczeć, że prawie udało ci się, mimo że wyskoczyłeś po pierwszej mili. i dlatego jest koniecznie tylko częściowo zdrowy i niekompletny. Oznacza to, że programy mogą nadal popsuć się z powodu właściwości, które nie są śledzone przez moduł sprawdzania typu, oraz że istnieją programy, które nie mogą się pomylić, mimo że nie mogą się pomylić. Impuls powodujący, że typowanie statyczne jest mniej częściowe i bardziej kompletne, powoduje, że systemy typów stają się nadmiernie skomplikowane i egzotyczne, o czym świadczą pojęcia takie jak „typy fantomowe” [11] i „chwiejne typy” [10]. To tak, jakby próbować przebiec maraton z piłką i łańcuchem przywiązanym do nogi i triumfalnie krzyczeć, że prawie udało ci się, mimo że wyskoczyłeś po pierwszej mili. i dlatego jest koniecznie tylko częściowo zdrowy i niekompletny. Oznacza to, że programy mogą nadal popsuć się z powodu właściwości, które nie są śledzone przez moduł sprawdzania typu, oraz że istnieją programy, które nie mogą się pomylić, chociaż nie mogą się pomylić. Impuls powodujący, że typowanie statyczne jest mniej częściowe i bardziej kompletne, powoduje, że systemy typów stają się nadmiernie skomplikowane i egzotyczne, o czym świadczą pojęcia takie jak „typy fantomowe” [11] i „chwiejne typy” [10]. To tak, jakby próbować przebiec maraton z piłką i łańcuchem przywiązanym do nogi i triumfalnie krzyczeć, że prawie udało ci się, mimo że wyskoczyłeś po pierwszej mili. i że istnieją programy, które choć nie mogą się pomylić, nie mogą być sprawdzane pod względem typu. Impuls powodujący, że typowanie statyczne jest mniej częściowe i bardziej kompletne, powoduje, że systemy typów stają się nadmiernie skomplikowane i egzotyczne, o czym świadczą pojęcia takie jak „typy fantomowe” [11] i „chwiejne typy” [10]. To tak, jakby próbować przebiec maraton z piłką i łańcuchem przywiązanym do nogi i triumfalnie krzyczeć, że prawie udało ci się, mimo że wyskoczyłeś po pierwszej mili. i że istnieją programy, które choć nie mogą się pomylić, nie mogą być sprawdzane pod względem typu. Impuls powodujący, że typowanie statyczne jest mniej częściowe i bardziej kompletne, powoduje, że systemy typów stają się nadmiernie skomplikowane i egzotyczne, o czym świadczą pojęcia takie jak „typy fantomowe” [11] i „chwiejne typy” [10]. To tak, jakby próbować przebiec maraton z piłką i łańcuchem przywiązanym do nogi i triumfalnie krzyczeć, że prawie udało ci się, mimo że wyskoczyłeś po pierwszej mili.

Zwolennicy języków dynamicznie typowanych twierdzą, że pisanie statyczne jest zbyt sztywne, a miękkość języków dynamicznych sprawia, że ​​idealnie nadają się do prototypowania systemów o zmieniających się lub nieznanych wymaganiach lub do interakcji z innymi systemami, które zmieniają się nieprzewidywalnie (integracja danych i aplikacji). Oczywiście języki dynamicznie typowane są niezbędne do radzenia sobie z naprawdę dynamicznymi zachowaniami programu, takimi jak przechwytywanie metod, ładowanie dynamiczne, kod mobilny, odbicie środowiska uruchomieniowego itp. W matce wszystkich artykułów na temat skryptów [16] John Ousterhout twierdzi, że systemy o typie statycznym języki programowania sprawiają, że kod jest mniej przydatny, bardziej szczegółowy, nie bardziej bezpieczny i mniej ekspresyjny niż języki skryptowe z dynamicznym pisaniem. Argument ten jest dosłownie papugowany przez wielu zwolenników dynamicznie pisanych języków skryptowych. Twierdzimy, że jest to błąd i należy do tej samej kategorii, co argumentowanie, że istotą programowania deklaratywnego jest wyeliminowanie przypisania. Lub, jak mówi John Hughes [8], logiczną niemożliwością jest uczynienie języka mocniejszym przez pominięcie funkcji. Obrona faktu, że opóźnianie sprawdzania typu do środowiska wykonawczego jest dobrą rzeczą, polega na stosowaniu taktyki strusi z faktem, że błędy należy wychwytywać możliwie jak najwcześniej. logiczną niemożliwością jest uczynienie języka mocniejszym przez pominięcie funkcji. Obrona faktu, że opóźnianie sprawdzania typu do środowiska wykonawczego jest dobrą rzeczą, polega na stosowaniu taktyki strusi z faktem, że błędy należy wychwytywać możliwie jak najwcześniej. logiczną niemożliwością jest uczynienie języka mocniejszym przez pominięcie funkcji. Obrona faktu, że opóźnianie sprawdzania typu do środowiska wykonawczego jest dobrą rzeczą, polega na stosowaniu taktyki strusi z faktem, że błędy należy wychwytywać możliwie jak najwcześniej.

Vinko Vrsalovic
źródło
37
„przechwytywanie metod, ładowanie dynamiczne, kod mobilny, odbicie środowiska uruchomieniowego” można wszystko zrobić w Javie, tylko dla zapisu.
Will Hartung,
13
Typy fantomów nie są „zbyt skomplikowane”.
Jon Harrop
12
Link do artykułu Meijer jest zepsuty od 16.05.2010.
jchadhowell
5
@jchadhowell, możesz to znaleźć tutaj research.microsoft.com/en-us/um/people/emeijer/Papers/...
Srinivas Reddy Thatiparthy
4
@ VinkoVrsalovic Języki statyczne z wnioskowaniem typu i polimorfizmem są dość dobre do szybkiego prototypowania. Oferują taki sam komfort jak język dynamiczny i bezpieczeństwo języków statycznych.
Edgar Klerks,
119

Systemy typu statycznego starają się eliminować niektóre błędy statycznie, sprawdzając program bez uruchamiania go i próbując udowodnić solidność pod pewnymi względami. Niektóre systemy typów są w stanie wychwycić więcej błędów niż inne. Na przykład język C # może wyeliminować wyjątki zerowego wskaźnika, jeśli jest używany poprawnie, podczas gdy Java nie ma takiej mocy. Twelf ma system typów, który faktycznie gwarantuje zakończenie prób , „rozwiązując” problem zatrzymania .

Jednak żaden system typów nie jest idealny. Aby wyeliminować określoną klasę błędów, muszą także odrzucić niektóre doskonale poprawne programy, które naruszają reguły. Właśnie dlatego Twelf tak naprawdę nie rozwiązuje problemu zatrzymania, po prostu unika go, rzucając dużą liczbę doskonale ważnych dowodów, które kończą się w dziwny sposób. Podobnie system typów Java odrzuca PersistentVectorimplementację Clojure z powodu użycia heterogenicznych tablic. Działa w czasie wykonywania, ale system typów nie może go zweryfikować.

Z tego powodu większość systemów typu zapewnia „ucieczki”, sposoby na zastąpienie sprawdzania statycznego. W większości języków mają one postać rzutowania, chociaż niektóre (jak C # i Haskell) mają całe tryby, które są oznaczone jako „niebezpieczne”.

Subiektywnie lubię pisanie statyczne. Prawidłowo zaimplementowany (podpowiedź: nie Java), system typu statycznego może być ogromną pomocą w usuwaniu błędów przed awarią systemu produkcyjnego. Języki o typie dynamicznym zwykle wymagają więcej testów jednostkowych, co w najlepszym przypadku jest nużące. Ponadto języki o typie statycznym mogą mieć pewne funkcje, które są niemożliwe lub niebezpieczne w systemach typu dynamicznego ( przychodzą mi na myśl niejawne konwersje ). Wszystko zależy od wymagań i subiektywnego gustu. Nie zbudowałbym kolejnego Eclipse w Rubim, niż próbowałbym napisać skrypt tworzenia kopii zapasowej w asemblerze lub załatać jądro za pomocą Java.

Aha, a ludzie, którzy mówią, że „ pisanie x jest 10 razy wydajniejsze niż pisanie y ”, po prostu dmuchają dymem. Pisanie dynamiczne może „czuć się” szybciej w wielu przypadkach, ale traci sens, gdy faktycznie próbujesz uruchomić fantazyjną aplikację . Podobnie, statyczne pisanie może wydawać się być idealną siatką bezpieczeństwa, ale jedno spojrzenie na niektóre bardziej skomplikowane ogólne definicje typów w Javie powoduje, że większość programistów pędzi w stronę osób niewidomych. Nawet przy systemach typu i wydajności nie ma srebrnej kuli.

Uwaga końcowa: nie martw się o wydajność podczas porównywania pisania statycznego z dynamicznym pisaniem. Nowoczesne JIT, takie jak V8 i TraceMonkey, niebezpiecznie zbliżają się do wydajności w języku statycznym. Fakt, że Java faktycznie kompiluje się do z natury dynamicznego języka pośredniego, powinien być wskazówką, że w większości przypadków dynamiczne pisanie nie jest ogromnym zabójcą wydajności, jak niektórzy to robią.

Daniel Spiewak
źródło
5
O występie. W zwykłych przypadkach nie robi to aż tak dużej różnicy, ale w matematyce wysokiego napięcia i tak dalej, jest prawdziwa różnica. Testy dowiodły, że wywołanie funkcji, w przypadku ipy vs C #, różni się tysiącem cykli. Tylko dlatego, że ten pierwszy musi mieć pewność, że istnieje metoda.
Dykam
29
można rozwinąć kwestię „C # może wyeliminować wyjątki zerowego wskaźnika, gdy jest właściwie używane, podczas gdy Java nie ma takiej mocy”. ? Przykład lub cytat byłyby bardzo mile widziane.
Srinivas Reddy Thatiparthy
13
„niektóre bardziej skomplikowane ogólne definicje typów w Javie powodują, że większość programistów pędzi w poszukiwaniu ślepców” - jeśli jest to twój najgorszy przykład, to oczywiście nie użyłeś C ++ ;-)
bacar 30.01.12
3
„Ponadto fakt, że Java faktycznie kompiluje się do z natury dynamicznego języka pośredniego, powinien być wskazówką, że w większości przypadków dynamiczne pisanie nie jest wielkim zabójcą wydajności, jak niektórzy to robią”. - jeśli przykładowym językiem z „dobrą wydajnością” jest Java, warto rozważyć to ponownie.
Yakk - Adam Nevraumont
Java kompiluje się do z natury dynamicznego pośrednika ” - to nie trafia w sedno. Kontrole statyczne zostały wykonane z wyprzedzeniem, dlatego nie są wymagane żadne dodatkowe kontrole w czasie wykonywania, ponieważ kompilator wybiera instrukcje podobne, daddponieważ z góry wie, że operandy są doubles.
Michael Beer
45

Cóż, obie są bardzo, bardzo, bardzo niezrozumiane, a także dwie zupełnie różne rzeczy. które nie wykluczają się wzajemnie .

Typy statyczne są ograniczeniem gramatyki języka. Można by powiedzieć, że statycznie wpisane języki nie są pozbawione kontekstu. Prosta prawda jest taka, że ​​niewygodne jest wyrażanie języka w sposób rozsądny w gramatyce bezkontekstowej, która nie traktuje wszystkich swoich danych po prostu jako wektorów bitowych. Systemy typu statycznego są częścią gramatyki języka, jeśli w ogóle istnieją, po prostu ograniczają go bardziej niż gramatyka bezkontekstowa, tak więc sprawdzanie gramatyki odbywa się w dwóch etapach nad źródłem. Typy statyczne odpowiadają matematycznemu pojęciu teorii typów, teoria typów w matematyce po prostu ogranicza legalność niektórych wyrażeń. Nie mogę powiedzieć 3 + [4,7]matematyki, że wynika to z teorii typów.

Typy statyczne nie są zatem sposobem „zapobiegania błędom” z teoretycznego punktu widzenia, są ograniczeniem gramatyki. Rzeczywiście, pod warunkiem, że +, 3 i interwały mają zwykle ustawione teoretyczne definicje, jeśli usuniemy system typów 3 + [4,7]ma całkiem dobrze określony wynik, który jest zbiorem. „błędy typu środowiska wykonawczego” teoretycznie nie istnieją, praktycznym zastosowaniem systemu typów jest zapobieganie operacjom, które dla ludzi nie miałyby sensu. Oczywiście operacje wciąż polegają jedynie na przesuwaniu i manipulowaniu bitami.

Problem polega na tym, że system typów nie może zdecydować, czy takie operacje będą miały miejsce, czy nie, czy będzie to dozwolone. Podobnie jak w, dokładnie podziel zestaw wszystkich możliwych programów na te, które będą miały „błąd typu”, a te, które nie są. Może zrobić tylko dwie rzeczy:

1: udowodnij, że błędy programu wystąpią w programie
2: udowodnij, że nie wystąpią w programie

Może się to wydawać, że sam sobie zaprzeczam. Ale to, co robi moduł sprawdzający typu C lub Java, to odrzuca program jako „niegramatyczny” lub jak nazywa go „błędem typu”, jeśli nie może się powieść o 2. Nie może udowodnić, że się nie wydarzy, to nie znaczy, że się nie zdarzy, to po prostu oznacza, że ​​nie może tego udowodnić. Może się zdarzyć, że program, który nie będzie zawierał błędu typu, zostanie odrzucony tylko dlatego, że nie może tego udowodnić kompilator. Prostym przykładem jestif(1) a = 3; else a = "string";, z pewnością ponieważ zawsze jest to prawdą, gałąź else nigdy nie zostanie wykonana w programie i nie wystąpi błąd typu. Ale nie może udowodnić tych przypadków w sposób ogólny, więc zostało odrzucone. Jest to główna słabość wielu statycznie typowanych języków, ponieważ chroniąc cię przed sobą, koniecznie jesteś chroniony również w przypadkach, gdy nie potrzebujesz.

Ale, w przeciwieństwie do powszechnego przekonania, istnieją również statyczne języki, które działają zgodnie z zasadą 1. Po prostu odrzucają wszystkie programy, których mogą udowodnić, że spowoduje błąd typu i przekazują wszystkie programy, których nie potrafią. Możliwe więc, że pozwalają programom, w których występują błędy typu, dobrym przykładem jest Typed Racket, hybryda pomiędzy pisaniem dynamicznym i statycznym. I niektórzy twierdzą, że masz w tym systemie to, co najlepsze z obu światów.

Kolejną zaletą typowania statycznego jest to, że typy są znane w czasie kompilacji, a zatem kompilator może z nich korzystać. Jeśli robimy to w Javie, "string" + "string"lub 3 + 3oba +tokeny w tekście na końcu reprezentują zupełnie inną operację i układ odniesienia, kompilator wie, który wybrać spośród samych typów.

Teraz zamierzam przedstawić bardzo kontrowersyjne stwierdzenie, ale pamiętajcie: „dynamiczne pisanie” nie istnieje .

Brzmi bardzo kontrowersyjnie, ale to prawda, dynamicznie pisane języki są z teoretycznego punktu widzenia nietypowe . Są to tylko statycznie pisane języki z tylko jednym typem. Innymi słowy, są to języki, które w praktyce są generowane gramatycznie przez gramatykę bezkontekstową.

Dlaczego nie mają typów? Ponieważ każda operacja jest zdefiniowana i dozwolona dla każdego operanta, czym dokładnie jest „błąd typu środowiska wykonawczego”? To z teoretycznego przykładu wyłącznie efekt uboczny . Jeśli robienie, print("string")które wypisuje łańcuch, jest operacją, to i tak length(3)pierwsza z nich ma efekt uboczny zapisu stringna standardowe wyjście, druga po prostu error: function 'length' expects array as argument.to jest to. Z teoretycznego punktu widzenia nie ma czegoś takiego jak dynamicznie pisany język. Są bez typu

W porządku, oczywistą zaletą „dynamicznie typowanego” języka jest moc ekspresji, a system typów jest niczym innym jak ograniczeniem mocy ekspresji. Ogólnie rzecz biorąc, języki z systemem typów rzeczywiście miałyby określony wynik dla wszystkich tych operacji, które nie są dozwolone, jeśli system typów byłby po prostu zignorowany, wyniki po prostu nie miałyby sensu dla ludzi. Wiele języków traci kompletność Turinga po zastosowaniu systemu typów.

Oczywistą wadą jest to, że mogą wystąpić operacje, które przyniosłyby bezsensowne dla ludzi wyniki. Aby temu zapobiec, dynamicznie pisane języki zwykle redefiniują te operacje, zamiast generować ten nonsensowny wynik, na nowo definiują go jako efekt uboczny polegający na zapisaniu błędu i prawdopodobnie całkowitym zatrzymaniu programu. W ogóle nie jest to „błąd”, w rzeczywistości specyfikacja języka implikuje to, jest to tak samo zachowanie języka, jak drukowanie łańcucha z teoretycznej perspektywy. Systemy typów zmuszają zatem programistę do uzasadnienia przepływu kodu, aby upewnić się, że tak się nie stanie. A zresztą rozum, że takmoże się przydać w niektórych punktach do debugowania, pokazując, że wcale nie jest to „błąd”, ale dobrze zdefiniowana właściwość języka. W efekcie jedyna pozostałość „dynamicznego pisania”, którą ma większość języków, chroni przed dzieleniem przez zero. Właśnie tym jest dynamiczne pisanie, nie ma typów, nie ma więcej typów niż to, że zero jest innym typem niż wszystkie inne liczby. To, co ludzie nazywają „typem”, jest po prostu inną właściwością układu odniesienia, taką jak długość tablicy lub pierwszy znak ciągu. Wiele dynamicznie wpisywanych języków pozwala także pisać takie rzeczy "error: the first character of this string should be a 'z'".

Inną rzeczą jest to, że dynamicznie pisane języki mają typ dostępny w czasie wykonywania i zwykle mogą go sprawdzić, poradzić sobie z nim i zdecydować na jego podstawie. Oczywiście w teorii nie różni się to od uzyskania pierwszego znaku tablicy i zobaczenia, co to jest. W rzeczywistości możesz stworzyć swój własny dynamiczny C, po prostu użyj tylko jednego typu, takiego jak long long int i użyj pierwszych 8 bitów, aby zapisać swój „typ” i odpowiednio pisać funkcje, które sprawdzają go i wykonują dodawanie zmiennoprzecinkowe lub całkowite. Masz statycznie wpisany język z jednym typem lub język dynamiczny.

W praktyce pokazuje to, że języki o typie statycznym są zwykle używane w kontekście pisania oprogramowania komercyjnego, podczas gdy języki o typie dynamicznym są zwykle używane w kontekście rozwiązywania niektórych problemów i automatyzacji niektórych zadań. Pisanie kodu w statycznie pisanych językach po prostu zajmuje dużo czasu i jest uciążliwe, ponieważ nie możesz robić rzeczy, o których wiesz, że okażą się w porządku, ale system typów wciąż chroni cię przed sobą przed błędami, których nie popełniasz. Wielu programistów nawet nie zdaje sobie sprawy, że to robią, ponieważ jest to w ich systemie, ale kiedy piszesz w językach statycznych, często omijasz fakt, że system typów nie pozwala ci robić rzeczy, które nie mogą pójść źle, ponieważ to nie mogę udowodnić, że nie pójdzie źle.

Jak zauważyłem, „typowanie statyczne” ogólnie oznacza przypadek 2, winny, dopóki nie zostanie udowodniony niewinności. Ale niektóre języki, które nie wywodzą swojego systemu typów z teorii typów, w ogóle stosują zasadę 1: Niewinni aż do udowodnienia winy, co może być idealną hybrydą. Więc może Typed Racket jest dla Ciebie.

Ponadto, dla bardziej absurdalnego i ekstremalnego przykładu, obecnie wdrażam język, w którym „typy” są naprawdę pierwszym znakiem tablicy, są to dane, dane „typu”, „typ”, który jest sam w sobie typ i układ odniesienia, jedyny układ odniesienia, który ma się jako typ. Typy nie są skończone ani ograniczone statycznie, ale nowe typy mogą być generowane na podstawie informacji o środowisku wykonawczym.

Zorf
źródło
1
„Wiele języków traci kompletność Turinga po zastosowaniu systemu typów”. nie dotyczy zwykłych języków programowania, prawda? z tego, co czytam, zwykłe języki nie są kompletne
Răzvan Flavius ​​Panda
1
@ RăzvanPanda: Lajla prawdopodobnie odnosił się do odmian rachunku różniczkowego typowanego lambda lub niektórych języków programowania, których używają na dowodach twierdzeń. Wiele z nich może wyrażać tylko programy, które mają gwarancję zatrzymania i dlatego nie są kompletne w Turingu. Praktyczne funkcjonalne języki programowania oparte na tych systemach typu omijają to ograniczenie, rozszerzając rachunek rdzenia o typy rekurencyjne.
hugomg
1
„Brzmi bardzo kontrowersyjnie, ale to prawda, że ​​dynamicznie pisane języki są z teoretycznego punktu widzenia nietypowe”. - ... i w jednej chwili wiem, że nie masz pojęcia o czym mówisz. Pisanie dynamiczne oznacza po prostu, że typy należą do wartości, a nie do identyfikatorów. Sprawia, że ​​programy są trudniejsze do udowodnienia, ale niekoniecznie niemożliwe. Inlineing i parametryczny polimorfizm już doprowadził do rozwoju optymalizacji czasu łącza; który rozwiązuje ten sam typ problemu, co kompilowanie optymalnych języków dynamicznie typowanych: który zna wszystkie możliwe dane wejściowe i wyjściowe.
DeftlyHacked
25

Być może największą zaletą dynamicznego pisania jest płytsza krzywa uczenia się. Nie ma żadnego systemu typów do nauczenia się i nie jest trywialna składnia dla przypadków narożnych, takich jak ograniczenia typu. To sprawia, że ​​pisanie dynamiczne jest dostępne dla znacznie większej liczby osób i jest wykonalne dla wielu osób, dla których zaawansowane systemy typu statycznego są poza zasięgiem. W związku z tym dynamiczne pisanie przyjęło się w kontekście edukacji (np. Scheme / Python na MIT) i języków specyficznych dla domeny dla osób niebędących programistami (np. Mathematica ). Języki dynamiczne przyjęły się także w niszach, w których mają niewielką lub żadną konkurencję (np. Javascript).

Najbardziej zwięzłe, dynamicznie typowane języki (np. Perl, APL, J, K, Mathematica ) są specyficzne dla dziedziny i mogą być znacznie bardziej zwięzłe niż najbardziej zwięzłe języki ogólnego przeznaczenia o typie statycznym (np. OCaml ) w niszach, dla których zostały zaprojektowane .

Główne wady dynamicznego pisania to:

  • Błędy typu wykonawczego.

  • Osiągnięcie tego samego poziomu poprawności może być bardzo trudne lub wręcz praktycznie niemożliwe i wymaga znacznie więcej testów.

  • Brak dokumentacji zweryfikowanej przez kompilator.

  • Niska wydajność (zwykle w czasie wykonywania, ale czasem w czasie kompilacji, np. Schemat Stalina) i nieprzewidywalna wydajność z powodu zależności od wyrafinowanych optymalizacji.

Osobiście wychowałem się na dynamicznych językach, ale nie chciałbym ich dotykać 40-biegunowym słupkiem jako profesjonalista, chyba że nie byłoby innych realnych opcji.

Jon Harrop
źródło
2
Powiedziałbym, że niższa bariera wejścia, ale opanowanie jest nie mniejszą krzywą uczenia się.
Erik Reppen
Czy krzywa uczenia się nie jest mniejsza, ponieważ nie masz systemu do nauki?
Jon Harrop,
Nadal istnieje system typów. Możesz rozsądnie zgadywać, co się stanie, gdy dodasz wartość bool i ciąg znaków, ale często bardzo pomaga poznanie niektórych faktycznych szczegółów na temat sposobu wymuszania typów w języku dynamicznie typowanym. Tego nie rozumie wielu ludzi wyłącznie ścisłych. Uczymy się tego.
Erik Reppen
@ErikReppen: Używamy różnych definicji „systemu typów”. Mówiłem o tym, że nie muszę się uczyć systemu typów statycznych, np. Typów danych algebraicznych, generycznych. „Typy”, o których mowa, to tylko dane. Fakt, że niektóre funkcje odrzucają niektóre dane w czasie wykonywania, jest uniwersalny.
Jon Harrop,
12

Z artykułu Artima : Typing: Strong vs. Słaby, Statyczny vs. Dynamiczny artykuł:

mocne pisanie zapobiega mieszaniu operacji między niedopasowanymi typami. Aby mieszać typy, musisz użyć jawnej konwersji

słabe pisanie oznacza, że ​​możesz mieszać typy bez wyraźnej konwersji

W pracy Pascala Costanzy „ Dynamiczne vs. statyczne pisanie - analiza oparta na wzorach” (PDF) twierdzi, że w niektórych przypadkach pisanie statyczne jest bardziej podatne na błędy niż pisanie dynamiczne. Niektóre języki o typie statycznym wymuszają ręczną emulację pisania dynamicznego w celu wykonania „Właściwej rzeczy”. Omówiono to w Lambda the Ultimate .

Mark Cidade
źródło
1
„pisanie statyczne jest bardziej podatne na błędy niż pisanie dynamiczne” - Tak, tak i PODWÓJNE tak! Mam duże doświadczenie w obu typach języków i za każdym razem język dynamiczny „po prostu działa”, podczas gdy statyczny wymaga 2x czasu debugowania (patrz C ++ i Delphi). Jest to często spowodowane problemami z typem, zwłaszcza przekazywaniem danych między modułami i funkcjami z typami szalonymi. Chociaż istnieją różne rodzaje błędów teoretycznych, które dynamiczne języki mogą powodować, w praktyce BARDZO rzadko spotykam się z błędem spowodowanym przymusem typu, chyba że jesteś słabym programistą nadużywającym typów dynamicznych.
dallin,
7
Kilka lat temu przeczytałem szkic artykułu Costanza. Wszędzie, gdzie pisał „statyczny”, miał na myśli konkretnie „Javę”. Dałem mu kilkadziesiąt przykładów w językach takich jak OCaml, które obaliły jego twierdzenia, ale i tak je opublikował. Wyglądając na ten artykuł, wciąż publikuje ten sam stary nonsens. Na przykład w tym artykule twierdzi, że „C # jest ogólnie złą kopią Java”. To nie ma miejsca w pracy naukowej ...
Jon Harrop,
@dallin moje doświadczenie jest zupełnie odwrotne: muszę dużo programować w C, C ++, Java, Python, Perl i tym podobnych, nigdy nie uruchomiłbym niczego większego niż mały program do poprawiania w dynamicznie pisanym języku, chyba że byłbym zmuszony. W Pythonie wciąż drżę, gdy myślę o projekcie WSGI: wywołania zwrotne, które musiałem przesadzić, zostały przekazane w referencjach obiektów, a kod wydawał się działać dobrze, gdy się zawiesił, ponieważ okazało się, że czasami nie są to obiekty, ale niektóre typy elementarne być przekazywane Język, który ułatwia tworzenie takich błędów, jest po prostu niebezpieczny.
Michael Beer
@MichaelBeer Można również powiedzieć, że język taki jak C / C ++, który pozwala bezpośrednio zarządzać pamięcią, jest po prostu niebezpieczny! Z pewnością zmagałem się z błędami pamięci przez wiele godzin. Ogromne projekty Java również nie są piknikiem. W każdym języku musisz zrozumieć niebezpieczeństwa związane z tym językiem i dobre praktyki. Absolutnie najgorsze projekty, nad którymi kiedykolwiek pracowałem, to zespołowe projekty PHP o małej strukturze, ale pracowałem również nad projektami z dynamicznymi językami, które były marzeniem, kiedy korzystały z dobrych ram i dobrych praktyk programistycznych.
dallin
@dallin Zgodził się, każdy język ma swoje pułapki. Ale wady, o których wspomniałem, są nieodłączne dla każdego języka o typie dynamicznym, możliwość bezpośredniego manipulowania pamięcią nie jest nieodłączną właściwością języków o typie statycznym. Możesz sobie wyobrazić dynamicznie pisane języki, które pozwalają bezpośrednio manipulować mem. Zgadzam się, że C ++ to prosta katastrofa, a twórca tego języka sam nie wierzy, że żadna osoba na tej planecie jest w stanie poznać wszystkie części języka. Nie można jednak winić za to statycznego pisania na C ++, ale potwora, który rośnie od 30 lat ...
Michael Beer
3

To zależy od kontekstu. Istnieje wiele korzyści, które są odpowiednie zarówno dla systemu dynamicznego pisania, jak i silnego pisania. Uważam, że przepływ języka typów dynamicznych jest szybszy. Języki dynamiczne nie są ograniczone atrybutami klas i myśleniem kompilatora o tym, co dzieje się w kodzie. Masz trochę swobody. Co więcej, język dynamiczny zwykle jest bardziej wyrazisty i powoduje mniej dobrego kodu. Mimo to jest bardziej podatny na błędy, co również jest wątpliwe i zależy bardziej od pokrycia testem jednostkowym. Jest to łatwy prototyp z dynamicznym językiem, ale konserwacja może stać się koszmarem.

Główną przewagą nad systemem typowania statycznego jest obsługa IDE i na pewno statyczny analizator kodu. Po każdej zmianie kodu stajesz się bardziej pewny kodu. Utrzymanie to spokój dzięki takim narzędziom.

AndrewG
źródło
0

Istnieje wiele różnych rzeczy na temat języków statycznych i dynamicznych. Dla mnie główna różnica polega na tym, że w językach dynamicznych zmienne nie mają ustalonych typów; zamiast tego typy są powiązane z wartościami. Z tego powodu dokładny kod, który zostanie wykonany, nie jest określony do czasu uruchomienia.

We wczesnych lub naiwnych implementacjach jest to ogromny problem z wydajnością, ale współczesne JIT są kusząco zbliżone do tego, co można uzyskać dzięki optymalizacji kompilatorów statycznych. (w niektórych skrajnych przypadkach, nawet lepiej niż to).

Javier
źródło
0

Chodzi o właściwe narzędzie do pracy. Żadne z nich nie jest lepsze w 100% przypadków. Oba systemy zostały stworzone przez człowieka i mają wady. Przykro nam, ale jesteśmy do kitu i robimy idealne rzeczy.

Lubię dynamiczne pisanie, ponieważ zrywa mi się z drogi, ale tak, błędy w czasie wykonywania mogą pełzać, których nie planowałem. Gdzie jako wpisywanie statyczne może naprawić wyżej wymienione błędy, ale doprowadza początkującego (w językach pisanych na maszynie) programistę do szaleństwa, próbując rzucić między stałym char i ciągiem.

JJ
źródło
-3

Pisanie statyczne: Języki, takie jak Java i Scala, są pisane statycznie.

Zmienne muszą zostać zdefiniowane i zainicjowane, zanim zostaną użyte w kodzie.

na przykład int x; x = 10;

System.out.println (x);

Pisanie dynamiczne: Perl jest językiem pisanym dynamicznie.

Zmienne nie muszą być inicjowane, zanim zostaną użyte w kodzie.

y = 10; użyj tej zmiennej w dalszej części kodu

Prachat
źródło
5
Nie ma to nic wspólnego z systemem typów.
Thiago Negri,