Jaki jest rzekomy wzrost wydajności pisania dynamicznego? [Zamknięte]


82

Często słyszałem twierdzenie, że języki z dynamicznym pisaniem są bardziej wydajne niż języki z pisaniem statycznym. Jakie są przyczyny tego roszczenia? Czy to nie tylko oprzyrządowanie z nowoczesnymi koncepcjami, takimi jak konwencja nad konfiguracją, wykorzystanie programowania funkcjonalnego, zaawansowane modele programowania i spójne abstrakty? Wprawdzie jest mniej bałaganu, ponieważ (na przykład w Javie) często nie są potrzebne redundantne deklaracje typu, ale można również pominąć większość deklaracji typów w językach o typie statycznym, które używają wnioskowania o typie, nie tracąc innych zalet pisania statycznego. Wszystko to jest również dostępne dla współczesnych języków o typie statycznym, takich jak Scala.

A więc: co można powiedzieć o wydajności z dynamicznym pisaniem, która naprawdę jest zaletą samego modelu pisma?

Wyjaśnienie: Bardziej interesują mnie duże / średnie projekty niż szybkie hacki. :-)


10
Czy spodziewałbyś się, że „duet statyczny” będzie szybszy lub bardziej produktywny niż „duet dynamiczny”?
Steve314,

Co masz na myśli z duetem? W każdym razie: mogę wymyślić kilka powodów, dla których pisanie statyczne jest bardziej produktywne niż pisanie dynamiczne: więcej sprawdzeń kompilatora pod kątem błędów, uzupełniania kodu, więcej informacji na temat zamiarów programisty w kodzie. Dlatego pytam o rozmowę.
Hans-Peter Störr

11
To był żart z racją. „Dynamiczny duet” to Batman i Robin. Nie wzbudzaliby tyle samo strachu w przestępczym świecie Gotham City, gdyby zostali nazwani „statycznym duetem”. Ponieważ programiści to ludzie, powierzchowne rzeczy mogą mieć znaczenie bez względu na to, co oznaczają te terminy.
Steve314,

Moje pierwsze pytanie dotyczy tego, czy wiem, co robię, czy nie. Jeśli tak, to mogę projektować rzeczy z wyprzedzeniem, a pisanie statyczne ma sens. Jeśli tego nie zrobię, będę musiał zmienić wiele rzeczy w locie, a dynamiczne pisanie będzie łatwiejsze. Common Lisp to najlepszy język, jaki znalazłem, gdy nie wiem, co robię. (Zastrzeżenie: Porysowałem tylko Haskella i dlatego nie mam dobrego wyczucia na podstawie statycznego pisania).
David Thornley,

2
Całkowicie zgadzam się z Johnem Skeetem msmvps.com/blogs/jon_skeet/archive/2009/11/17/…
użytkownik

Odpowiedzi:


99

Myślę, że to dość bliskie połączenie. Zarówno pisanie dynamiczne, jak i pisanie statyczne mają swoje zalety.

Powody, dla których dynamiczne pisanie jest bardziej wydajne:

  • Jest bardziej zwięzły - wiele niepotrzebnych kodów może zostać usuniętych, jeśli wszystko jest dynamicznie wpisywane - deklaracje typów, logika rzutowania typów itp. Wszystkie inne rzeczy są równe, krótszy kod jest nieznacznie szybszy do napisania, ale co ważniejsze, może być szybszy do odczytania i zachowaj (ponieważ nie musisz przedzierać się przez wiele stron kodu, aby zrozumieć, co się dzieje)
  • Łatwiejsze do „zhakowania” techniki, takie jak pisanie na kaczkach i łatanie małp, mogą szybko uzyskać wyniki (choć mogą cię później pomylić…)
  • Bardziej interaktywne - dynamiczne pisanie jest prawdopodobnie bardziej odpowiednie do interaktywnego programowania podobnego do REPL do szybkiego prototypowania, debugowania w czasie rzeczywistym uruchomionych instancji programu, a nawet kodowania na żywo.
  • Przypadki testowe mogą wychwycić błędy środowiska wykonawczego - przy założeniu, że używasz TDD lub przynajmniej masz dobry zestaw testów, powinno to wykryć wszelkie problemy z pisaniem w kodzie.
  • Lepszy polimorfizm - języki dynamiczne mogą potencjalnie zachęcać do tworzenia polimorficznych funkcji i abstrakcji, które mogą zwiększyć wydajność i ponowne wykorzystanie kodu. Clojure na przykład doskonale wykorzystuje dynamiczny polimorfizm w wielu abstrakcjach .
  • Prototypy - prototypowe modele danych / obiektów są moim zdaniem silniejsze i bardziej elastyczne niż dziedziczne dziedziczenia dziedziczone. Języki dynamiczne częściej umożliwiają lub zachęcają do podejścia opartego na prototypach, czego doskonałym przykładem jest Javascript.

Powody, dla których pisanie statyczne jest bardziej wydajne:

  • Lepszy projekt - zmuszenie do myślenia o typach wartości w oprogramowaniu z góry może popchnąć cię w kierunku czystszych, bardziej logicznych rozwiązań. (Mówię, że mogę - nadal można zaprojektować naprawdę zły kod ...)
  • Lepsze sprawdzanie czasu kompilacji - wpisywanie statyczne może pozwolić na wykrycie większej liczby błędów w czasie kompilacji. Jest to ogromna zaleta i jest prawdopodobnie najlepszą rzeczą w językach statycznych.
  • Automatyczne uzupełnianie - wpisywanie statyczne może również dostarczać więcej informacji do IDE, dzięki czemu automatyczne uzupełnianie kodu lub wyszukiwanie dokumentacji jest bardziej skuteczne.
  • Odradza włamania - musisz zachować dyscyplinę w kodzie, co może być zaletą dla długoterminowej łatwości konserwacji.
  • Wnioskowanie typu - w niektórych językach (np. Scala) może to zapewnić wiele zwięzłych korzyści płynących z dynamicznych języków, przy jednoczesnym zachowaniu dyscypliny typów.

Średnio doszedłem do wniosku (po wielu latach doświadczenia po obu stronach ogrodzenia), że dynamiczne pisanie na klawiaturze może być bardziej produktywne w krótkim okresie, ale ostatecznie staje się trudne do utrzymania, chyba że masz bardzo dobre zestawy testów i dyscyplinę testowania.

Z drugiej strony faktycznie wolę podejścia typowane statycznie, ponieważ uważam, że korzyści z poprawności i obsługa narzędzi zapewniają lepszą wydajność w dłuższej perspektywie.


14
+1, bardzo szczegółowa odpowiedź. Wartość punktu „Lepsze sprawdzanie czasu kompilacji” nie może być wystarczająco podkreślona.
NoChance

8
Oprócz wnioskowania typu istnieje również przeciążenie w stylu Haskell, szablony C ++, generyczne i być może niektóre inne funkcje językowe, które zapewniają pewne zalety pisania kaczego w ramach statycznego pisania - o ile obiekt zapewnia wymagany interfejs (to „kwakanie jak kaczka”) możesz go użyć, prawie niezależnie od typu nominalnego tego obiektu. „Prawie” wynika z tego, że niektóre podejścia wymagają pewnego rodzaju „znachorów tego typu”, takich jak deklaracja odpowiedniego rodzaju kaczki - np. Deklaracja „klasy” w Haskell.
Steve314,

45
Muszę zdecydowanie nie zgodzić się z twoim twierdzeniem, że „krótszy kod ... jest szybszy do odczytania i utrzymania”. Jest krok pośredni, zrozumienie kodu. Musiałem utrzymywać kod innych ludzi zarówno w Delphi, jak i JavaScript, a kod Delphi jest znacznie łatwiejszy do zrozumienia, ponieważ jest bardziej szczegółowy. A szczególnie dlatego, że kod Delphi ma deklaracje typu, a JavaScript nie. Kiedy mamy do czynienia z czymś bardziej złożonym niż prymitywy, deklaracje typów sprawiają, że banalne jest sprawdzenie, jakie są twoje zmienne i co mogą zrobić, co jest niezbędną wiedzą do prac konserwacyjnych.
Mason Wheeler

21
Zaczynam się nie zgadzać z większością podanych tutaj powodów. Weź Haskell, który prawdopodobnie ma najściślejszy system typów. Ma REPL (właściwie co najmniej dwa), cechuje się bardzo silnym polimorfizmem poprzez dopasowywanie wzorców na konstruktorach i jest tak zwięzły, jak można się spodziewać - znacznie więcej niż JavaScript czy Python. Sądzę więc, że niektóre z powodów, o których wspominasz, są przypadkowe, a nie nieodłączne dla luźno pisanych języków.
Andrea

15
Nie pokładałbym zbyt dużego zaufania w „przypadkach testowych”. Nie można ich porównać z dobrym systemem typów. System typów zapewnia dowód, że twoja funkcja zostanie już wywołana z co najmniej poprawnymi parametrami, podczas gdy przypadki testowe mogą dostarczyć tylko dowodów empirycznych. Jednak nawet te dowody zebrano ze sztucznego otoczenia.
Ingo

56

Dzięki dynamicznym językom możesz pisać kiepski kod szybciej niż podczas używania języka pisanego na maszynie.

Po szybkim utworzeniu ogromnej kupy dynamicznych rzeczy możesz bezpiecznie przejść do innego projektu bez konieczności dbania o długoterminową konserwację.

To wzrost wydajności :)

Żartuję, ale po zaangażowaniu się w projekt wykorzystujący „dynamiczny język” przestraszyłem się ilością niepotrzebnych testów, dokumentacji i konwencji, z którymi musisz sobie poradzić, jeśli chcesz mieć działający produkt.
I z radością wielu błędów w czasie wykonywania, które mogły zostać wykryte podczas kompilacji.
Och, zapomniałem też o tych wszystkich hackach i voodoach, które metaprogramowanie pozwala wam wprowadzić w kodzie!

Tak więc wzrost wydajności może być mitem dla średnich / dużych projektów w całym okresie jego eksploatacji.


11
Tak, moje doświadczenie jest takie samo. 100-liniowy skrypt perla jest w porządku i bez tak wspaniałych narzędzi zgubilibyśmy się. Ale 100-liniowy projekt perlowy najprawdopodobniej będzie koszmarem.
Ingo

3
... a potem masz JavaScript (nie tylko dynamiczny, ale także słabo wpisany).
Den

16

Istnieje również teoretyczny pogląd na ten problem: statyczny system typów jest zasadniczo wyspecjalizowanym prover twierdzeniem, który akceptuje program tylko wtedy, gdy może udowodnić jego poprawność typu. Wszystkie systemy typu statycznego odrzucają niektóre prawidłowe programy, ponieważ żaden rozstrzygalny system typu statycznego nie jest wystarczająco silny, aby udowodnić wszystkie możliwe programy z poprawnym typem.

Można argumentować, że programy, których nie można sprawdzić za pomocą statycznego sprawdzania typów, są hackami i / lub złym stylem, ale jeśli masz już prawidłowy program, a sprawdzanie typów go nie akceptuje, z pewnością ma to negatywny wpływ na produktywność w krótkim okresie.

Niektóre przypadki, w których można zauważyć, że blokator typów przeszkadza, to z ogólnymi kontenerami i ko / kontrawariancją w argumentach i typach zwracanych.


18
I odwrotnie, jeśli błędnie wprowadziłeś niepoprawny program, kompilator poinformuje Cię natychmiast i podświetli złą linię. poprawia to produktywność w porównaniu do zauważenia nieudanego uruchomienia testowego i debugowania w celu znalezienia błędu.
MarkJ

5
ogólne pojemniki i wyraźna ko-kontrowariancja mają „wchodzić ci w drogę”, jeśli zrobisz to źle. jaka jest korzyść ze skompilowania kodu, który zawiedzie w czasie wykonywania?
M.Stramm

Zwykle zadanie uważa się za wykonane w 0%, dopóki pomyślnie nie przeprowadzi wszystkich testów. Tylko wtedy twój postęp można uznać za coś więcej niż nic. Mając to na uwadze, nie sądzę, że warto mierzyć produktywność na czymś, co nie zostało jeszcze ukończone.
Pijusn

-1 Nie odnosi się do rzeczywistego pytania („wzrost wydajności”, pamiętasz?). Prawdopodobnie nie chcesz nawet pisać „prawidłowych programów odrzucanych przez system typów”. To, że możesz, nie oznacza, że ​​powinieneś. A dlaczego miałbyś w ogóle mieć „prawidłowy program”, który odrzuca sprawdzający typ? Co, kodowałeś program Javascript i nagle próbowałeś go skompilować w Javie?
Andres F.,

Te prawidłowe programy, które odrzuca system typów, mogą pomóc w skróceniu kodu, co prowadzi do mniejszej liczby błędów, których system typów nie jest w stanie zrozumieć (mniej kodu = mniej błędów). Kompilator / IDE podświetlający wiersz może być wykonywany w dynamicznych językach z wartościami testowymi (tj. Programowaniem opartym na REPL), abyś mógł zobaczyć wartości pośrednie i mogą wykryć błędy, których twój system typów nie może tak dobrze, jak błędy typu. Można również użyć wnioskowania typu statycznego, aby uzyskać ostrzeżenia o typie.
aoeu256

15

Jedną z zalet, którą znalazłem w przypadku najbardziej dynamicznych języków, jest to, że ułatwiają pisanie bardziej ogólnego kodu. O wiele łatwiej jest pisać na wyższym poziomie abstrakcji, gdy nie trzeba walczyć z systemem typów, aby to zrobić.

Nie musisz o tym tyle myśleć - pisanie kodu, który robi coś nietrywialnego z dowolnym obiektem w Javie, jest trudne i prawdopodobnie wymaga refleksji, która jest zasadniczo dynamicznie typowana; z czymś takim jak JavaScript, pisanie funkcji, która robi coś interesującego dla wszystkich obiektów, jest drugą naturą. Doskonałym przykładem może być funkcja, którą niedawno napisałem, która pobiera obiekt i zastępuje wszystkie jego metody metodami, które robią to samo, ale także uruchamiają zdarzenie. Nie mam pojęcia, jak podejść do czegoś takiego w Javie. Jednak nie jestem pewien, ile z tego wynika z systemów typów, a ile z innych różnic językowych.

Jednak ostatnio zacząłem używać Haskell. Haskell pozwala mi pisać abstrakcyjny, ogólny kod tak łatwo, jak każdy dynamicznie pisany język, którego użyłem. Mój powyższy przykład Java / JavaScript nie ma sensu w Haskell, ponieważ nie ma obiektów, metod, zdarzeń ani nawet wielu mutacji, ale inne rodzaje ogólnego kodu są naprawdę łatwe do napisania.

W rzeczywistości Haskell może napisać ogólny kod, którego nie potrafią dynamicznie pisane języki; doskonałym przykładem jest readfunkcja, która jest w zasadzie przeciwieństwem toString. Można dostać Intlub Doubleczy cokolwiek typ chcesz (tak długo, jak to jest w pewnej klasy typu). Można nawet mieć polimorficzne stałe , więc maxBoundmoże być maksymalna Int, Double, Char... itd., Wszystko w zależności od tego, jakiego typu to ma być.

Moja teoria jest teraz taka, że ​​wzrost wydajności dzięki zastosowaniu dynamicznego języka jest zawsze w porównaniu do języków takich jak Java z mniej wydajnymi, bardziej szczegółowymi i mniej elastycznymi systemami typów.

Jednak nawet system pisma Haskell ma pewne irytujące problemy, których nie miałbyś w dynamicznie pisanym języku. Najbardziej denerwuje mnie sposób, w jaki obsługiwane są liczby; na przykład, musisz zadzierać z systemem typów, aby używać length(z listy) podwójnie, z czym bez problemów nie miałbyś problemów. Kolejną irytującą rzeczą, na którą się natknąłem, jest praca z Word8(typu int bez znaku) i funkcje, które oczekują Int.

Tak więc ostatecznie brak systemu typów ułatwia pisanie kodu ogólnego bez zbytniego zastanawiania się, a także pozwala uniknąć irytujących pułapek systemów typu. Nigdy nie musisz walczyć z systemem czcionek w dynamicznym języku, ale nie możesz na nim polegać.


1
Tak, z jakiegoś powodu trudno jest uzyskać prawidłowe systemy liczbowe. W Scali jest to również bałagan. Myślę, że dynamiczne systemy typowe podbijają proste statyczne systemy typowe pod względem łatwości pracy z nim, ale przegrywają z bardziej zaawansowanymi (jak Scala, Haskell, ML itp., Które wszystkie wykorzystują warianty systemu-F ).
Edgar Klerks,

3
Twoja odpowiedź jest rozsądna, ale zawiera błędy. Po pierwsze, nie jest prawdą, że języki dynamiczne „nie mają systemu typów”, więc nie może to być powodem, dla którego „ułatwiają pisanie kodu ogólnego”. Nie ułatwiają tego, jak pokazuje twój własny kontrprzykład z Haskellem (obalasz własne twierdzenie!). „Nigdy nie musisz walczyć z systemem typów” jest fałszem: walczysz z nim za każdym razem, gdy musisz naprawić błąd spowodowany niewystarczającą statyczną kontrolą typu. Wreszcie jawne wymuszanie Intzwrotu przez listę jest banalne; przykład: 1.0 + fromIntegral (length myList)tj. po prostu użyj fromIntegral.
Andres F.,

2
Wreszcie „szybkie pisanie kodu!” = „Większa produktywność”. Twój kod musi działać! Jeśli piszesz błędne oprogramowanie, które musisz później poświęcić na debugowanie i naprawianie, nie jesteś produktywny.
Andres F.,

„bez myślenia za dużo” czerwona flaga dla tego, co większość ludzi ma na myśli, mówiąc, że dynamicznie pisane języki są „bardziej produktywne”
Ataraxia

Jeśli systemy typów naprawdę poprawiły wydajność, gdzie znajdują się wszystkie przydatne aplikacje w Haskell lub Idris? Myślę, że ważniejsze mogą być takie kwestie, jak łatwość zrozumienia błędu typu, „łatalność” (możliwość edytowania aplikacji w nieprzewidywalny sposób) i 90% kontrola błędów dokumentów i wnioskowania o typie.
aoeu256

7

P: Często słyszałem twierdzenie, że języki z dynamicznym pisaniem są bardziej wydajne niż języki z statycznym pisaniem. Jakie są przyczyny tego roszczenia?

Ma to przyczyny historyczne. Jeśli cofniesz się o kilka dekad, języki dynamiczne były bezsprzecznie znacznie wydajniejsze niż języki statyczne (choć znacznie wolniejsze). Perl jest wyraźnie bardziej produktywny niż C, jeśli znasz oba i jedno z zadań na to pozwala. Jednak z biegiem czasu wiele języków zapożyczało się od siebie, a nowsze języki zmniejszają lukę (zarówno pod względem wydajności, jak i wydajności).

Oto kilka punktów do rozważenia:

Śmieci : Śmieci to ogromny wzrost wydajności. Wierzę, że Java była pierwszym głównym językiem statycznym z GC. Wcześniej statyczne oznaczało w zasadzie ręczne zarządzanie pamięcią. (Uwaga: tutaj i poniżej rozważam tylko języki głównego nurtu. Istnieje wiele języków eksperymentalnych i niszowych, które zapewnią kontrprzykłady w każdym punkcie, który podniosę.)

Bezpieczeństwo pamięci : Jest to poprawa wydajności, dzięki której nie musisz się martwić o strzelanie sobie w stopę. Przed „zarządzanymi” językami statycznymi, takimi jak Java, statyczny zwykle oznaczał bezpośredni dostęp do pamięci. Debugowanie jest również częścią wydajności, a niebezpieczny dostęp do pamięci może prowadzić do naprawdę niejasnych błędów.

Uciążliwe systemy typu. Przed wprowadzeniem sparametryzowanych typów (takich jak szablony lub generyczne) w językach statycznych ograniczenia systemów typów statycznych często stanowiły obciążenie. Na przykład w Javie trzeba było jawnie spuszczać za każdym razem, gdy wybierasz element z kolekcji. Masz syntaktyczny narzut obsady i nie masz żadnego bezpieczeństwa. Biorąc pod uwagę, jak wszechobecne są kolekcje w programowaniu, była to poważna wada.
Konieczność zadeklarowania rodzaju wszystkiego jest zbyteczna, ale przy nowoczesnym wnioskowaniu można to znacznie zmniejszyć.

Duża standardowa biblioteka. Python był reklamowany jako „dołączone baterie” ze względu na dużą standardową bibliotekę. To w porównaniu z C, które mają bardzo minimalistyczną standardową bibliotekę. Jednak w przypadku platform takich jak Java i .net ogromna standardowa biblioteka staje się standardem, a nowsze języki, takie jak Scala i F #, dziedziczą to „za darmo”.

Struktury danych pierwszej klasy. Dynamiczne języki, takie jak Perl i Python, mają wbudowane pierwszorzędne struktury danych, takie jak listy i mapy, z wygodnymi skrótami składniowymi do typowych operacji. W porównaniu z tym C nie ma wbudowanych kolekcji oprócz tablic o stałym rozmiarze.

Zamknięcia i składnia lambda - języki dynamiczne zwykle miały to od samego początku, ale języki statyczne przyjęły to, ostatnio Java.

REPL umiejętność szybkiego testowania fragmentów kodu interaktywnie jest ogromnym dobrodziejstwem. Ale chociaż narzędzia IDE, takie jak „bezpośrednie” okno w Visual Studio, języki statyczne mogą do pewnego stopnia to emulować.

Zaawansowane oprzyrządowanie - oprócz powyższych punktów, w których języki statyczne zbliżają się do wygody języków dynamicznych, nowi redaktorzy korzystają z analizy statycznej w taki sposób, że języki dynamiczne mają trudności z dopasowaniem. Na przykład redaktorzy mogą zapewnić bezpieczne automatyczne refaktoryzacje, co jest ściśle mówiąc niemożliwe w dynamicznym języku.

Konkluzja: Historycznie to była prawda, ale dziś odpowiedź jest mniej jednoznaczna.


P: Więc: co można powiedzieć o wydajności z dynamicznym pisaniem, która naprawdę jest zaletą samego modelu pisma?

Nieco trudno jest oddzielić dynamiczny model pisania od dynamicznych języków, ale na przykład C # przyjęło bardziej dynamiczne funkcje z czasem, mimo że jego rdzeniem jest język statyczny. To naprawdę dowód na korzyść modelu typu dynamicznego. Przykłady:

Odbicie Odbicie jest zasadniczo funkcją dynamicznego pisania. Rodzaje obiektów są sprawdzane w środowisku wykonawczym niż czas kompilacji. Kiedy został wprowadzony, było to trochę zaniepokojone, ale w C # użycie odbicia staje się coraz bardziej wszechobecne, na przykład ASP.Net MVC mocno wykorzystuje odbicie.

Atrybuty Atrybuty są przykładem dynamicznego pisania. Możesz dodać dowolne atrybuty do klasy w czasie kompilacji, a następnie sprawdzać w czasie wykonywania (poprzez odbicie) i manipulować obiektami na jej podstawie. Coś w rodzaju MEP to w zasadzie struktura rozszerzenia oparta na modelu typu dynamicznego.

Linq do SQL, EF mv. Różne transformatory Linq sprawdzają zapytania jako obiekty wykonawcze i generują sql w locie. Nie robi się bardziej dynamiczny niż sprawdzanie kodu w czasie wykonywania. CodeDom to druga strona medalu, w której kod może być generowany w czasie wykonywania

Roslyn Roslyn w zasadzie implementuje eval, co kiedyś uważano za cechę definiującą naprawdę dynamiczny język.

Dynamiczny Typ dynamicjest najbardziej dynamiczną funkcją w języku C # i jest reklamowany w celu uproszczenia i zwiększenia wydajności interakcji z obiektami zewnętrznymi i językami. Ale dla wygody jest również używany w Asp.net MVC.

Zaleta wszystkich powyższych funkcji pokazuje, że model dynamiczny ma określone zalety nawet w języku statycznym z typami sparametryzowanymi, typami strukturalnymi i wnioskowaniem typu.


Naprawdę nie podoba mi się ta odpowiedź, ponieważ prawie wszystkie punkty nie odnoszą się do podstawowego pytania: „Jaki jest rzekomy wzrost wydajności pisania dynamicznego ?” nie dynamiczne języki .
niania

@nanny, czy mógłbyś rozwinąć swoją postrzeganą różnicę między dynamicznymi językami pisanymi i dynamicznymi językami? (jest to jedna z tych niewyraźnych rzeczy). Czy możesz podać przykład dynamicznego języka maszynowego, który nie jest językiem dynamicznym, wraz z jasnymi definicjami każdego z nich?

@nanny: Pytanie faktycznie dotyczy „dynamicznie pisanych języków”, a nie tylko „dynamicznego pisania”.
JacquesB,

@MichaelT Przepraszam, że nie było jasne. Pisanie dynamiczne jest jednym z aspektów wszystkich języków dynamicznych. Ta odpowiedź mówi o innym aspekcie, z historycznego punktu widzenia dynamicznym języku, który faktycznie nie występuje w części dotyczącej dynamicznego pisania.
niania

1
@nanny: Odpowiadam w zasadzie na to: „Często słyszałem twierdzenie, że języki dynamicznie pisane są bardziej wydajne niż języki statyczne. Jakie są powody tego roszczenia?” - Uważam, że powody tego twierdzenia są historyczne i dotyczą nie tylko dynamicznego pisania, ale także innych funkcji poprawiających wydajność dynamicznych języków.
JacquesB

6

Wszystkie nowoczesne funkcje językowe są tak duże, że pisanie statyczne vs. dynamiczne nie ma większego znaczenia.

Zasadą jest, że im lepsze funkcje językowe, tym krótszy kod. To całkiem proste. Java pokazuje, jak pisanie statyczne może się nie udać, co daje przeciwnikom wiele do jedzenia. Źle zaprojektowane funkcje językowe generalnie wiążą się z pewnymi kosztami, a statyczne pisanie w Javie jest po pierwsze obowiązkową funkcją (w przeciwnym razie większość osób prawdopodobnie nawet by jej nie użyła), a po drugie źle wykonane.
Właśnie dlatego w porównaniu świecą najbardziej dynamiczne języki, chociaż twierdzę, że PHP tak naprawdę nie poprawia twojego życia w ogóle (przynajmniej do niedawna), z powodu wielu innych dziwactw niezwiązanych z systemami typów.

Z drugiej strony masz wiele języków z ekspresyjnymi systemami typowania, które nie przeszkadzają i nawet nie są obowiązkowe. Niektóre z nich pozwalają nawet na osadzanie kodu bez typu, gdy tylko trzeba uciec z systemu typów.

Osobiście używam haXe, który jest językiem z wnioskowaniem typu, zarówno podtypem nominalnym, jak i strukturalnym, opcjonalnym nietypowym kodem, typami funkcji pierwszej klasy, algebraicznymi typami danych i (niezbyt dojrzałymi, ale niezwykle potężnymi) makrami leksykalnymi, unikając przy tym tajemnej składni. Po około 3 latach używania haXe doszedłem do prostego wniosku:

Programowanie staje się znacznie łatwiejsze, gdy twój język nie blokuje cię w religijnych wyborach dotyczących paradygmatów, ale stara się być po prostu dobrym narzędziem. Istnieje wiele języków statycznych i dynamicznych oraz języków mieszanych , które odniosły sukces. Niektóre z nich są łatwe do nauczenia, a najtrudniejsze do opanowania.
Ich moc wynika ze sposobu, w jaki poszczególne funkcje można komponować, aby łatwo tworzyć proste rozwiązania skomplikowanych problemów. Wyklucza to pewną ortogonalność, którą można osiągnąć jedynie poprzez delikatną równowagę włączenia lub pominięcia wszystkich zbadanych do tej pory cech językowych. Jeśli spróbujesz dodać statyczne pisanie do Ruby, okaleczysz go, jeśli spróbujesz zabrać go Haskellowi, zmiażdżysz go. W przeciwieństwie do tego: jeśli zabierzesz go z C, ludzie prawie tego nie zauważą, a jeśli zabierzesz go z Javy, niektórzy mogą ci podziękować.

Z własnego doświadczenia mogę ci powiedzieć: lubię Ruby. Poszerzyło to moje horyzonty i sposób projektowania systemów. IMHO powinno się przede wszystkim uczyć programowania ludzi. Jest dyskretny, mocny, zwięzły, zabawny. Rozumiem, dlaczego spodoba się komuś, kto pochodzi z języka ortodoksyjnego.
Na dłuższą metę jednak pisanie statyczne pozwala odroczyć pracę analizatorowi statycznemu, a przy wnioskowaniu typu jest to zasadniczo bezpłatne. W rezultacie powstaje kod, który jest łatwiejszy w utrzymaniu i często działa szybciej.

Ale znowu, samo pisanie statyczne nic nie da. To kwestia połączenia. Myślę, że gdzieś pomiędzy F #, Scala, Nemerle, OCaml lub haXe możesz znaleźć swój własny optymalny. Ale to ostatecznie zależy od ciebie, ponieważ język powinien pozwolić ci na osadzenie myśli bez wysiłku, zamiast zmuszać cię do zginania ich wokół siebie. W końcu nic nie daje większego wzrostu wydajności, niż gdyby programowanie było zabawne.


„Zasadą jest, że im lepsze funkcje językowe, tym krótszy kod”. Na pewnym poziomie może to wynikać z opinii, ale nie sądzę, aby to stwierdzenie było dokładne. Krótszy kod sam w sobie nie oferuje zbyt wielu korzyści, poza tym, że wymaga mniej pisania podczas pisania i może zajmować mniej miejsca na dysku (co zresztą nie jest czynnikiem w językach kompilowanych). Myślę, że znakiem dobrego języka jest przekazanie jak największej ilości informacji o tym, co robi w możliwie najbardziej zwięzły sposób. Pisanie dynamiczne nie jest zbyt samok dokumentujące i w wyniku tego traci łatwość obsługi
Ataraxia,

Możesz uzupełnić dynamiczny kod o informacje takie jak wartości domyślne / argumenty słów kluczowych, typy uzyskane z wnioskowania o typie, wnioskowanie o typie dynamicznym z kompilatora JIT lub po prostu rejestrując wszystkie funkcje [przejdź przez każdą funkcję lub klasę w uruchomionym programie i zastąp je wersja funkcji, która rejestruje swoje argumenty / wyniki). Następnie możesz zobaczyć dziennik poprzednich uruchomień funkcji. Innym pomysłem jest odrzucenie kodu, który nie zawiera adnotacji typu, kontraktów wykonawczych ani przykładowych testów sesji REPL, ale daje programistom opcję wyboru jednej z trzech.
aoeu256

3

Osobiście jedyny powód, dla którego dynamiczne pisanie jest pomocne, to jeśli jesteś naprawdę wolnym maszynistą lub budujesz gigantyczne funkcje / metody / wieloryby, które są trudne w nawigacji. Musisz także przejść do problemu z testowaniem całej jednostki. Typy dynamiczne wymagają (chyba że lubisz pisać zepsuty kod) energicznych testów jednostkowych (Aby upewnić się, że typy dynamiczne nie wybuchają niespodziewanie (tj. Zmienna jest głównie kaczką, ale czasami dcuk przypadkowo)). Statyka będzie starać się o wiele bardziej starać, aby temu zapobiec (i tak, możesz argumentować za energicznymi testami jednostkowymi)


0

Myślę, że przede wszystkim musisz zdefiniować „produktywność”. Co oznacza „produktywność” i obejmuje?

Jeśli przez „bardziej produktywny” rozumiesz pisanie mniejszej liczby wierszy kodu w celu zaimplementowania tej samej funkcji, to tak, języki programowania z dynamicznym pisaniem są bardziej „produktywne” niż języki z pisaniem statycznym.

Jeśli jednak weźmiesz również pod uwagę czas poświęcony na debugowanie i naprawianie błędów, języki pisania dynamicznego mogą nie być tak produktywne, ponieważ języki pisania dynamicznego mają tendencję do wypychania sprawdzania błędów do czasu wykonywania, podczas gdy w przeciwieństwie do języków pisania statycznego może wykonać sprawdzanie błędów w czasie kompilacji. Ponieważ powszechnie przyjmuje się, że im później błąd zostanie znaleziony, tym droższe jest jego usunięcie. W związku z tym kodowanie dynamiczne może powodować generalnie taką samą, a może nawet mniejszą produktywność niż kodowanie statyczne.


Zasadniczo nie jest prawdą, że można napisać obiekt w mniejszej liczbie wierszy, używając dynamicznego języka. Które języki i tak porównujesz?
Andres F.,

@AndresF. Och, używam głównie Pythona i C ++.
yaobin,

1
Ok, ale nie można uogólniać dynamicznego na statyczny, gdy faktycznie porównuje się Python i C ++. C ++ nie jest szczególnie reprezentatywnym przykładem języka z pisaniem statycznym. Istnieją niezwykle zwięzłe, statycznie pisane języki, które mniej więcej pozwalają pisać programy tak krótkie jak w Pythonie. Ogólnie rzecz biorąc, twoje twierdzenie jest fałszywe.
Andres F.

Tak, ale co, jeśli edytujesz swój program, gdy jest on nadal uruchomiony? Wszelkie problemy z czasem wykonywania wystąpią po prostu i możesz je naprawić właśnie tam. W Lisp za każdym razem, gdy pojawia się błąd, możesz po prostu naprawić program, a następnie kontynuować działanie ... Tak, w przypadku bardziej złożonych ścieżek adnotacje byłyby dobre [być może możesz używać stopniowego pisania, takiego jak mypy i lisp], ale te bardziej złożone ścieżki mają również możliwość błędów nietypowych, więc unikanie skomplikowanych ścieżek w dowolnym języku może być dobrym pomysłem.
aoeu256

-1

Dużą zaletą dynamicznego pisania jest wydajność.

Python, Ruby itp. Oprócz dynamicznego pisania (wiele innych parametrów, słowniki wbudowane w typy itp.) Mają wiele innych programów zwiększających produktywność. Łączny wpływ na produktywność programisty jest imponujący.

Kary pod względem szybkości (lub braku!) I zużycia zasobów nie są tak złe, jak można by się spodziewać, aw większości przypadków rekompensuje je szybkość i elastyczność rozwoju.

Jest na ten temat (bardzo stary!) Artykuł . Jest to jedno z niewielu właściwie przeprowadzonych badań dotyczących wydajności programisty, a wiele wniosków jest nadal aktualnych.

Czym (prawdopodobnie) byłyby inne badania, które zostaną przeprowadzone dzisiaj:

  1. Java JVM poprawiły się nie do poznania.
  2. Nowoczesne środowiska IDE poprawiłyby produktywność koderów C ++ i Java, ale w niewielkim stopniu wpłynęły na języki skryptowe.
  3. C # zostanie uwzględnione i prawdopodobnie będzie w tym samym parku co Java, ale nieco lepiej.

Komunikat brzmi, chyba że wydajność jest naprawdę poważnym problemem. Dynamiczne języki zwiększą produktywność.


2
Moja niejasność jest dokładnie tym, co robi dynamiczne pisanie w celu zwiększenia wydajności. Artykuł jest interesujący, ale dotyczy bardzo małego programu i nie jestem pewien, jak to przenosi się do wielu tysięcy wierszy kodu w większości programów.
Hans-Peter Störr

5
W badaniu wykorzystano tylko C, C ++ i Java jako przykłady języków statycznych, a następnie podjęto próbę zastosowania wniosków ogólnie do tradycyjnych języków programowania. Wszystkie trzy języki mają tę samą podstawową składnię, z tymi samymi wadami zmniejszającymi produktywność, co powoduje, że porównanie jest nieważne. Nie jest tak, że języki statyczne są nieproduktywne, to, że rodzina C jest nieproduktywna. Gdyby w swoich testach zastosowali dialekt Pascala, najprawdopodobniej doszliby do innych wniosków.
Mason Wheeler

@mason - w tej dziedzinie jest bardzo niewiele obiektywnych badań. Jest to jedno z niewielu prawdziwych badań z rzeczywistymi liczbami itp. Program „przykładowy” nie jest trywialny! Łączy elementy obsługi słownika, złożone algorytmy i duże ilości danych. Wysoki odsetek nieudanych i zawieszających się prób potwierdza nietrywialny charakter zadania.
James Anderson

2
-1 Nie mówisz wiele o tym, co sprawia, że ​​dynamiczne języki maszynowe są bardziej wydajne. Domyślne parametry i słowniki można znaleźć w językach o typie statycznym, takich jak np. Scala.
Jonas

1
@JamesAnderson Co gorsza, papier, do którego prowadzisz link, nie popiera nawet twojej tezy. Porównuje „języki skryptowe” (często dynamiczne) z „ konwencjonalnymi językami” (często statycznymi). Powiedz mi, czym dokładnie „konwencjonalne” języki? Czy uważasz, że jest taki sam jak zestaw języków ze statycznym pisaniem? Co gorsza, papier nie jest już tak stary. Do 2000 roku istniało już wiele świetnych języków ze statycznym pisaniem, które były prawdopodobnie wydajniejsze niż języki dynamiczne.
Andres F.,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.