Czytam prezentację z informacją „JavaScript nie ma typu”. Zaprzeczało to temu, co uważałem za prawdę, więc zacząłem kopać, aby dowiedzieć się więcej.
Każda odpowiedź na pytanie Czy JavaScript jest językiem bez typu? mówi, że JavaScript nie jest pozbawiony typu i oferuje przykłady różnych form statycznego, dynamicznego, silnego i słabego pisania, które znam i które mi się podobają ... więc nie była to droga.
Zapytałem więc Brendana Eicha, twórcę JavaScript, a on odpowiedział:
typy akademickie używają „bez typu” w znaczeniu „brak typów statycznych”. są wystarczająco sprytni, aby zobaczyć, że wartości mają typy (no!). kontekst ma znaczenie.
Czy specjaliści od informatyki akademickiej używają „bez typu” jako synonimu „dynamicznie wpisywana” (i czy jest to poprawne?), Czy jest coś głębszego w tym, czego mi brakuje? Zgadzam się z Brendanem, że kontekst jest ważny, ale wszelkie cytowania wyjaśnień byłyby świetne, ponieważ moje obecne książki „przejdź do” nie grają w piłkę na ten temat.
Chcę to naprawić, aby móc lepiej zrozumieć, a nawet Wikipedia nie odwołuje się do tego alternatywnego zastosowania (które i tak mogę znaleźć). Nie chcę mieć problemów z używaniem tego terminu lub kwestionowaniem jego użycia w przyszłości, jeśli się mylę :-)
(Widziałem też topowego Smalltalkera, który powiedział, że Smalltalk też jest „bez typu”, więc nie jest to jednorazowy przypadek, co skłoniło mnie do podjęcia tego zadania! :-))
źródło
Odpowiedzi:
Tak, to standardowa praktyka w literaturze akademickiej. Aby to zrozumieć, warto wiedzieć, że pojęcie „typu” zostało wynalezione w latach trzydziestych XX wieku w kontekście rachunku lambda (właściwie nawet wcześniej, w kontekście teorii mnogości). Od tamtej pory wyłoniła się cała gałąź logiki obliczeniowej, zwana „teorią typów”. Na tych podstawach opiera się teoria języka programowania. We wszystkich tych matematycznych kontekstach „typ” ma szczególne, ugruntowane znaczenie.
Termin „dynamiczne typowanie” został wynaleziony znacznie później - i jest sprzecznością terminów w obliczu powszechnego matematycznego użycia słowa „typ”.
Na przykład, oto definicja „systemu typów”, której Benjamin Pierce używa w swoim standardowym podręczniku Typy i języki programowania :
Zwraca też uwagę:
Wydaje się, że większość osób pracujących w tej dziedzinie podziela ten punkt widzenia.
Zauważ, że tak nie jest oznacza to, że „bez typu” i „wpisane dynamicznie” są synonimami. Raczej, że to drugie jest (technicznie mylącą) nazwą dla konkretnego przypadku tego pierwszego.
PS: A FWIW, tak się składa, że jestem zarówno akademickim badaczem systemów typów, jak i nieakademickim wdrażającym JavaScript, więc muszę żyć ze schizmą. :)
źródło
"[dynamically typed] is a (technically misleading) name for a particular case of [untyped]"
Jestem akademickim informatykiem specjalizującym się w językach programowania i tak, słowo „bez typu” jest często (niewłaściwie) używane w ten sposób. Byłoby miło zarezerwować to słowo do użytku z językami, które nie mają dynamicznych tagów typu, takich jak Forth i kod asemblera, ale te języki są rzadko używane, a nawet rzadziej studiowane, ao wiele łatwiej jest powiedzieć „bez typu” niż „wpisywane dynamicznie”.
Bob Harper lubi mówić, że języki takie jak Scheme, Javascript i tak dalej powinny być traktowane jako języki wpisywane tylko z jednym typem: typ: wartość. Skłaniam się do tego poglądu, ponieważ umożliwia on zbudowanie spójnego światopoglądu przy użyciu tylko jednego rodzaju formalizmu.
PS W czystym rachunku lambda jedynymi „wartościami” są wyrazy w postaci normalnej, a jedynymi zamkniętymi wyrazami w postaci normalnej są funkcje. Jednak większość naukowców korzystających z rachunku lambda dodaje typy bazowe i stałe, a następnie albo dołączasz statyczny system typów dla lambda, albo wracasz od razu do dynamicznych tagów typów.
PPS Do oryginalnego plakatu: jeśli chodzi o języki programowania, a zwłaszcza systemy czcionek, informacje w Wikipedii są słabej jakości. Nie ufaj temu.
źródło
Przyjrzałem się temu i stwierdziłem, że odpowiedź na twoje pytanie jest prosta i zaskakująca: „tak”: akademickie typy CS, a przynajmniej niektóre z nich, używają „bez typu” w znaczeniu „dynamicznie wpisywane”. Na przykład w książce Programming Languages: Principles and Practices , Third Edition (Kenneth C. Louden i Kenneth A. Lambert, opublikowano w 2012 r.):
[ link ] (uwaga: pogrubienie w oryginale) i dalej używa słowa „bez typu” tylko w ten sposób.
Uważam to za zaskakujące (z tych samych powodów, które podają afrischke i Adam Mihalcin), ale tak jest. :-)
Edytowano, aby dodać: więcej przykładów można znaleźć, podłączając się
"untyped languages"
do Google Book Search. Na przykład:- Jacob Matthews i Amal Ahmed, 2008 [ link ]
- Charles Consel, 1990 [ link ]
Nawiasem mówiąc, po przejrzeniu tych wyników wyszukiwania mam wrażenie, że jeśli badacz pisze o „nietypowym” języku funkcjonalnym, to najprawdopodobniej uważa go za „bez typu” w tym samym sensie, co bez typu lambda rachunek różniczkowy, o którym wspomina Adam Mihalcin. Przynajmniej kilku badaczy wspomina Scheme i rachunek lambda jednym tchem.
To, czego wyszukiwanie nie mówi, oczywiście, to czy są badacze, którzy odrzucają tę identyfikację i nie uważają tych języków za „bez typu”. Cóż, znalazłem to:
- ktoś (nie wiem kto), 1998 [ link ]
ale oczywiście większość ludzi, którzy odrzucają tę identyfikację, nie czułaby potrzeby, aby to wprost powiedzieć.
źródło
Bez typu i dynamicznie wpisywane absolutnie nie są synonimami. Językiem, który jest najczęściej nazywany „bez typu”, jest Rachunek Lambda, który jest właściwie językiem niezatyfikowanym - wszystko jest funkcją, więc możemy statycznie udowodnić, że typem wszystkiego jest funkcja. Język z typami dynamicznymi ma wiele typów, ale nie dodaje sposobu, aby kompilator mógł je statycznie sprawdzić, zmuszając kompilator do wstawiania sprawdzeń środowiska uruchomieniowego dla typów zmiennych.
Następnie JavaScript jest językiem dynamicznie typowanym: możliwe jest pisanie programów w JavaScript w taki sposób, że jakaś zmienna
x
może być liczbą, funkcją, ciągiem znaków lub czymś innym (i określenie, który z nich wymagałby rozwiązania problemu zatrzymania lub czegoś trudny problem matematyczny), więc możesz zastosowaćx
argument, a przeglądarka musi sprawdzić w czasie wykonywania, czyx
jest to funkcja.źródło
Oba stwierdzenia są poprawne, w zależności od tego, czy mówisz o wartościach, czy o zmiennych. Zmienne JavaScript są bez typu, wartości JavaScript mają typy, a zmienne mogą wahać się w zakresie dowolnego typu wartości w czasie wykonywania (tj. „Dynamicznie”).
W JavaScript i wielu innych językach wartości, a nie zmienne, mają typy. Wszystkie zmienne mogą obejmować wszystkie typy wartości i mogą być traktowane jako „dynamicznie wpisane” lub „bez typu” - z punktu widzenia sprawdzania typu zmienna, która nie ma / niepoznawalnego typu, a zmienna, która może przyjmować dowolny typ, jest logicznie i praktycznie równoważna . Kiedy teoretycy typów mówią o językach i typach, zwykle o tym mówią - zmienne przenoszące typy - ponieważ są zainteresowani pisaniem programów do sprawdzania typów i kompilatorów itd., Które działają na tekście programu (tj. Zmiennych), a nie na uruchomionym programie w pamięci (tj. wartości).
W przeciwieństwie do innych języków, takich jak C, zmienne mają typy, ale wartości nie. W językach takich jak Java zmienne i wartości mają typy. W C ++ niektóre wartości (te z funkcjami wirtualnymi) mają typy, a inne nie. W niektórych językach możliwa jest nawet zmiana typów przez wartości, chociaż zwykle jest to uważane za zły projekt.
źródło
To pytanie dotyczy semantyki
Jeśli podam ci te dane:
12
jaki to jest typ? Nie masz pewności. Może to być liczba całkowita - może to być liczba zmiennoprzecinkowa - może być ciągiem znaków. W tym sensie jest to bardzo dużo „nietypowych” danych.Jeśli podam wam wyimaginowany język, który pozwala na użycie operatorów takich jak „dodawanie”, „odejmowanie” i „łączenie” na tych danych i innych dowolnych fragmentach danych, to „typ” jest nieco nieistotny (dla mojego języka wyobrażonego) (przykład : być
add(12, a)
wydajności109
co jest12
także wartości ASCIIa
).Porozmawiajmy przez chwilę o C. C prawie pozwala ci robić, co chcesz, z dowolnymi danymi. Jeśli używasz funkcji, która zajmuje dwa
uint
s - możesz rzutować i przekazywać wszystko, co chcesz - a wartości zostaną po prostu zinterpretowane jakouint
s. W tym sensie C jest „bez typu” (jeśli potraktujesz to w taki sposób).Jednak - i dochodząc do sedna Brendana - jeśli powiem ci, że „mój wiek jest
12
” - to12
ma typ - przynajmniej wiemy, że jest numeryczny. Z kontekstem wszystko ma swój typ - niezależnie od języka.Dlatego powiedziałem na początku - twoje pytanie dotyczy semantyki. Jakie jest znaczenie „bez typu”? Myślę, że Brendan trafił w sedno, kiedy powiedział „żadnych statycznych typów” - bo to wszystko, co może oznaczać. Ludzie w naturalny sposób dzielą rzeczy na typy. Intuicyjnie wiemy, że między samochodem a małpą jest coś zasadniczo innego - nigdy nie uczono nas, jak dokonywać takich rozróżnień.
Wracając do mojego przykładu na początku - język, który "nie dba o typy" (per se), może pozwolić ci "dodać" "wiek" i "imię" bez generowania błędu składniowego ... ale to nie oznacza, że jest to logicznie uzasadniona operacja.
Javascript może pozwolić ci robić różne szalone rzeczy bez uważania ich za "błędy". To nie znaczy, że to, co robisz, jest logicznie uzasadnione. To dla programisty do rozwiązania.
Czy system / język, który nie wymusza bezpieczeństwa typów w czasie kompilacji / budowania / interpretacji, jest „bez typu” lub „wpisywany dynamicznie”?
Semantyka.
EDYTOWAĆ
Chciałem coś tutaj dodać, ponieważ niektórzy ludzie wydają się być złapani na „tak, ale Javascript ma kilka„ typów ””.
W komentarzu do cudzej odpowiedzi powiedziałem:
W Javascript mógłbym mieć obiekty, które utworzyłem jako „Małpy” i obiekty, które utworzyłem jako „Ludzie”, a niektóre funkcje mogą działać tylko na „Ludziach”, inne tylko na „Małpach”, i jeszcze inni tylko na „Things With Arms”. To, czy w języku kiedykolwiek powiedziano, że istnieje taka kategoria obiektów jak „rzeczy z bronią”, jest równie nieistotne dla asemblera („bez typu”), jak dla JavaScript („dynamiczne”). To kwestia logicznej integralności - a jedynym błędem byłoby użycie czegoś, co nie ma broni z tą metodą.
Tak więc, jeśli uważasz, że JavaScript ma pewne „pojęcie typów” wewnętrznie - i stąd „typy dynamiczne” - i myślisz, że jest to w jakiś sposób „wyraźnie różniące się od systemu bez typu” - powinieneś zobaczyć z powyższego przykładu, że jakiekolwiek „pojęcie typy, które ma wewnętrznie, jest naprawdę nieistotne.
Aby wykonać tę samą operację z C #, na przykład, POTRZEBUJĘ interfejsu o nazwie
ICreatureWithArms
lub czegoś podobnego. Inaczej w Javascript - nie w C czy ASM.Oczywiście to, czy Javascript w ogóle rozumie „typy”, nie ma znaczenia.
źródło
is there something deeper to this that I am missing
i myślę, że niezrozumienie, że jest to kwestia semantyczna, jest głębszą sprawą - więc zrobiłem, co mogłem, by wrzucić wszystko, co mogłem.JavaScript has types
w swojej odpowiedzi).Chociaż prawdą jest, że większość badaczy CS, którzy piszą o typach, zasadniczo traktuje tylko języki z typami dającymi się wyprowadzać składniowo jako języki typowane, o wiele więcej z nas używa języków dynamicznie / latentnie wpisanych na maszynie, którzy nie lubią tego użycia.
Uważam, że istnieją 3 typy [SIC] języków:
Bez typu - tylko operator określa interpretację wartości - i generalnie działa na wszystkim. Przykłady: asembler, BCPL
Statycznie typowane - wyrażenia / zmienne mają skojarzone z nimi typy, które określają interpretację / ważność operatora w czasie kompilacji. Przykłady: C, Java, C ++, ML, Haskell
Typowane dynamicznie - wartości mają skojarzone z nimi typy, a ten typ określa interpretację / ważność operatora w czasie wykonywania. Przykłady: LISP, Scheme, Smalltalk, Ruby, Python, Javascript
O ile mi wiadomo, wszystkie języki dynamicznie typowane są bezpieczne dla typów - tzn. Tylko prawidłowe operatory mogą operować na wartościach. Ale to samo nie dotyczy języka z typami statycznymi. W zależności od mocy stosowanego systemu typów, niektórzy operatorzy mogą być sprawdzani tylko w czasie wykonywania lub wcale. Na przykład większość języków z typami statycznymi nie obsługuje poprawnie przepełnienia liczb całkowitych (dodanie 2 dodatnich liczb całkowitych może dać ujemną liczbę całkowitą), a odwołania do tablic poza granicami albo nie są w ogóle sprawdzane (C, C ++), albo są sprawdzane tylko w w czasie wykonywania. Co więcej, niektóre systemy typów są tak słabe, że użyteczne programowanie wymaga kresek ucieczki (rzutowania w C i rodzinie), aby zmienić typ wyrażeń w czasie kompilacji.
Wszystko to prowadzi do absurdalnych twierdzeń, na przykład, że C ++ jest bezpieczniejszy niż Python, ponieważ jest (wpisywany statycznie), podczas gdy prawda jest taka, że Python jest samoistnie bezpieczny, podczas gdy można odstrzelić sobie nogę w C ++.
źródło
Nie jestem informatykiem, ale byłbym raczej zdziwiony, gdyby słowa „bez typu” były rzeczywiście używane jako synonim „dynamicznie typowane” w społeczności CS (przynajmniej w publikacjach naukowych), ponieważ imho te dwa terminy opisują różne pojęcia. Język z typami dynamicznymi ma pojęcie typów i wymusza ograniczenia typu w czasie wykonywania (nie można na przykład podzielić liczby całkowitej przez ciąg w Lisp bez otrzymywania błędu), podczas gdy język bez typu nie ma żadnego pojęcia typów w wszystko (np. asembler). Nawet artykuł Wikipedii o językach programowania (http://en.m.wikipedia.org/wiki/Programming_language#Typed_versus_untyped_languages) czyni to rozróżnienie.
Aktualizacja: Może zamieszanie wynika z faktu, że niektóre teksty mówią coś do tego stopnia, że „zmienne nie są wpisywane” w JavaScript (co jest prawdą). Ale to nie oznacza automatycznie, że język jest bez typu (co byłoby fałszywe).
źródło
Zgadzam się z Brendanem - kontekst jest wszystkim.
Moje podanie:
Pamiętam, że byłem zdezorientowany około 2004 roku, ponieważ pojawiły się kłótnie dotyczące tego, czy Ruby nie był typowany, czy dynamicznie wpisywany. Ludzie ze starej szkoły C / C ++ (których byłem jednym z nich) myśleli o kompilatorze i mówili, że Ruby nie ma typu.
Pamiętaj, że w języku C nie ma typów środowiska uruchomieniowego, są tylko adresy i jeśli wykonywany kod zdecyduje się traktować wszystko, co znajduje się pod tym adresem, jako coś, czego nie ma, to ups. To zdecydowanie nietypowe i bardzo różni się od dynamicznie wpisywanego.
W tym świecie „pisanie” dotyczy tylko kompilatora. C ++ miał „mocne typowanie”, ponieważ testy kompilatora były bardziej rygorystyczne. Java i C były bardziej „słabo typowane” (pojawiły się nawet spory o to, czy Java jest napisana silnie, czy słabo). Języki dynamiczne były w tym kontinuum „bez typu”, ponieważ nie miały sprawdzania typu kompilatora.
Dzisiaj, dla praktykujących programistów, jesteśmy tak przyzwyczajeni do języków dynamicznych, że oczywiście myślimy o braku typu, który oznacza brak kompilatora lub sprawdzania typu interpretera, co byłoby niesamowicie trudne do debugowania. Ale był tam okres, w którym nie było to oczywiste, aw bardziej teoretycznym świecie CS może nawet nie mieć znaczenia.
W pewnym sensie nic nie może być pozbawione typu (lub prawie nic, w każdym razie), ponieważ musisz mieć zamiar manipulowania wartością, aby napisać sensowny algorytm. To świat teoretycznego CS, który nie zajmuje się szczegółami implementacji kompilatora lub interpretera dla danego języka. Więc „bez typu” jest (prawdopodobnie nie wiem) całkowicie bez znaczenia w tym kontekście.
źródło