Język programowania - Programming language

Z Wikipedii, wolnej encyklopedii

Kodu źródłowego za pomocą prostego programu komputerowego napisany w języku programowania C . Po skompilowaniu i uruchomieniu daje wynik „ Hello, world! ”.

Język programowania jest język formalny zawierający komplet strun , które produkują różnego rodzaju wyjścia kodu maszynowego . Języki programowania są wykorzystywane w programowaniu komputerowym do implementacji algorytmów .

Większość języków programowania składa się z instrukcji dla komputerów . Istnieją programowalne maszyny, które używają zestawu konkretnych instrukcji zamiast ogólnych języków programowania . Od początku XIX wieku programy były używane do kierowania zachowaniem maszyn, takich jak krosna żakardowe , pozytywki i pianina . Programy dla tych maszyn (takie jak zwoje pianina) nie powodowały różnych zachowań w odpowiedzi na różne sygnały wejściowe lub warunki.

Powstały tysiące różnych języków programowania, a każdego roku powstają kolejne. Wiele języków programowania jest napisanych w trybie imperatywnym (tj. Jako sekwencja operacji do wykonania), podczas gdy inne języki używają formy deklaratywnej (tj. Określa się pożądany wynik, a nie sposób jego osiągnięcia).

Opis języka programowania jest zwykle podzielony na dwa składniki składni (forma) i semantyki (znaczenie). Niektóre języki są zdefiniowane w dokumencie specyfikacji (na przykład język programowania C jest określony przez normę ISO ), podczas gdy inne języki (takie jak Perl ) mają dominującą implementację, która jest traktowana jako odniesienie . Niektóre języki mają oba, przy czym język podstawowy jest zdefiniowany przez standard i rozszerzenia zaczerpnięte z dominującej implementacji są powszechne.

Definicje

Język programowania to notacja służąca do pisania programów , które są specyfikacjami obliczeń lub algorytmów . Niektórzy autorzy ograniczają termin „język programowania” do tych języków, które mogą wyrazić wszystkie możliwe algorytmy. Cechy często uważane za ważne dla tego, co stanowi język programowania, obejmują:

Funkcja i cel
Język programowania komputer jest język używany do pisania programów komputerowych , które wiąże się z komputera do wykonywania jakiejś obliczeń lub algorytm i może sterować urządzeniami zewnętrznymi, takimi jak drukarki , dyski twarde , robotów , i tak dalej. Na przykład programy PostScript są często tworzone przez inny program do sterowania drukarką lub wyświetlaczem komputera. Mówiąc bardziej ogólnie, język programowania może opisywać obliczenia na jakiejś, być może abstrakcyjnej, maszynie. Ogólnie przyjmuje się, że pełna specyfikacja języka programowania zawiera opis, prawdopodobnie wyidealizowany, maszyny lub procesora dla tego języka. W większości praktycznych kontekstów język programowania obejmuje komputer; w konsekwencji języki programowania są zwykle definiowane i badane w ten sposób. Języki programowania różnią się od języków naturalnych tym, że języki naturalne są używane tylko do interakcji między ludźmi, podczas gdy języki programowania umożliwiają także ludziom przekazywanie instrukcji maszynom.
Abstrakcje
Języki programowania zwykle zawierają abstrakcje do definiowania i manipulowania strukturami danych lub kontrolowania przepływu wykonania . Praktyczną konieczność, aby język programowania obsługiwał odpowiednie abstrakcje, wyraża zasada abstrakcji . Ta zasada jest czasami formułowana jako zalecenie dla programisty, aby właściwie wykorzystywał takie abstrakcje.
Ekspresyjna moc
Teoria obliczeń klasyfikuje języki przez obliczeń są one zdolne do wyrażania. Wszystkie języki z pełną wersją Turinga mogą implementować ten sam zestaw algorytmów . ANSI / ISO SQL-92 i Charity to przykłady języków, które nie są kompletne w języku Turing, ale są często nazywane językami programowania.

Języki znaczników, takie jak XML , HTML lub troff , które definiują dane strukturalne , zwykle nie są uważane za języki programowania. Języki programowania mogą jednak dzielić składnię z językami znaczników, jeśli zdefiniowano semantykę obliczeniową. Na przykład XSLT jest kompletnym językiem Turinga wykorzystującym w całości składnię XML. Ponadto LaTeX , który jest używany głównie do tworzenia struktury dokumentów, zawiera również kompletny podzbiór Turinga.

Termin język komputerowy jest czasami używany zamiennie z językiem programowania. Jednak użycie obu terminów różni się w zależności od autorów, w tym dokładny zakres każdego z nich. Jedno użycie opisuje języki programowania jako podzbiór języków komputerowych. Podobnie języki używane w informatyce, które mają inny cel niż wyrażanie programów komputerowych, są ogólnie określanymi językami komputerowymi. Na przykład języki znaczników są czasami określane jako języki komputerowe, aby podkreślić, że nie są one przeznaczone do programowania.

Inne użycie traktuje języki programowania jako konstrukcje teoretyczne do programowania abstrakcyjnych maszyn , a języki komputerowe jako ich podzbiór, który działa na komputerach fizycznych, które mają ograniczone zasoby sprzętowe. John C. Reynolds podkreśla, że języki specyfikacji formalnej to tyle samo języków programowania, co języków przeznaczonych do wykonania. Twierdzi również, że tekstowe, a nawet graficzne formaty wejściowe, które wpływają na zachowanie komputera, są językami programowania, mimo że często nie są kompletne w języku Turinga, i zauważa, że ​​nieznajomość pojęć języka programowania jest przyczyną wielu błędów w formatach wejściowych.

Historia

Wczesne wydarzenia

Bardzo wczesne komputery, takie jak Colossus , były programowane bez pomocy zapisanego programu , poprzez modyfikację ich obwodów lub ustawienie banków fizycznych elementów sterujących.

Nieco później programy mogą być pisane w języku maszynowym , w którym programista zapisuje każdą instrukcję w postaci numerycznej, którą sprzęt może wykonać bezpośrednio. Na przykład, instrukcja dodania wartości w dwóch lokalizacjach pamięci może składać się z 3 liczb: „kodu operacji”, który wybiera operację „dodawania”, oraz dwóch lokalizacji pamięci. Programy w postaci dziesiętnej lub binarnej były odczytywane z kart perforowanych , taśmy papierowej, taśmy magnetycznej lub włączane na przełącznikach na panelu przednim komputera. Języki maszynowe zostały później nazwane językami programowania pierwszej generacji (1GL).

Następnym krokiem było opracowanie tak zwanych języków programowania drugiej generacji (2GL) lub języków asemblera , które nadal były ściśle powiązane z architekturą zestawu instrukcji konkretnego komputera. Dzięki temu program stał się znacznie bardziej czytelny dla człowieka i zwolnił programistę z żmudnych i podatnych na błędy obliczeń adresów.

Pierwsze języki programowania wysokiego poziomu lub języki programowania trzeciej generacji (3GL) zostały napisane w latach pięćdziesiątych XX wieku. Wczesnym językiem programowania wysokiego poziomu, który miał być zaprojektowany dla komputera, był Plankalkül , opracowany dla niemieckiego Z3 przez Konrada Zuse w latach 1943-1945. Jednak nie został wdrożony do 1998 i 2000 roku.

John Mauchly „s Code Krótki , zaproponowany w 1949 roku, był jednym z pierwszych języków wysokiego poziomu, jaki kiedykolwiek powstał na komputer elektroniczny . W przeciwieństwie do kodu maszynowego , instrukcje Short Code reprezentowały wyrażenia matematyczne w zrozumiałej formie. Jednak program musiał być tłumaczony na kod maszynowy za każdym razem, gdy był uruchamiany, co powodowało, że proces był znacznie wolniejszy niż uruchamianie równoważnego kodu maszynowego.

Na Uniwersytecie w Manchesterze , Alick Glennie opracowany bez kodowania na początku 1950 roku. Jako język programowania używał kompilatora do automatycznej konwersji języka na kod maszynowy. Pierwszy kod i kompilator został opracowany w 1952 roku dla komputera Mark 1 na Uniwersytecie w Manchesterze i jest uważany za pierwszy skompilowany język programowania wysokiego poziomu.

Drugi autokod został opracowany dla Mark 1 przez RA Brookera w 1954 roku i został nazwany „Mark 1 Autocode”. Brooker opracował również autokod dla Ferranti Mercury w latach pięćdziesiątych we współpracy z Uniwersytetem w Manchesterze. Wersja dla EDSAC 2 została opracowana przez DF Hartley z University of Cambridge Mathematical Laboratory w 1961 roku. Znana jako EDSAC 2 Autocode, była ona bezpośrednim rozwinięciem Mercury Autocode dostosowanym do lokalnych warunków i została uznana za optymalizację kodu obiektowego i język źródłowy diagnostyka, która była zaawansowana w tamtym czasie. Współczesny, ale odrębny wątek rozwoju, Atlas Autocode został opracowany dla maszyny Atlas 1 Uniwersytetu w Manchesterze .

W 1954 roku, FORTRAN został wynaleziony w IBM przez Johna Backusa . Był to pierwszy szeroko stosowany język programowania ogólnego przeznaczenia wysokiego poziomu, który miał funkcjonalną implementację, a nie tylko projekt na papierze. Wciąż jest popularnym językiem do obliczeń o wysokiej wydajności i jest używany w programach, które porównują i oceniają najszybsze superkomputery na świecie .

Inny wczesny język programowania został wymyślony przez Grace Hopper w USA, zwany FLOW-MATIC . Został opracowany dla UNIVAC I w Remington Rand w okresie od 1955 do 1959 roku. Hopper odkrył, że klienci przetwarzający dane biznesowe nie czują się komfortowo z notacją matematyczną, a na początku 1955 roku ona i jej zespół napisali specyfikację dla języka programowania w języku angielskim i wdrożyli prototyp. Kompilator FLOW-MATIC stał się publicznie dostępny na początku 1958 r. I był w znacznym stopniu ukończony w 1959 r. FLOW-MATIC miał znaczący wpływ na projekt COBOL , ponieważ tylko on i jego bezpośredni następca AIMACO były w tym czasie w użyciu.

Udoskonalenie

Zwiększone wykorzystanie języków wysokiego poziomu wprowadziło wymóg dotyczący języków programowania niskiego poziomu lub języków programowania systemu . Języki te w różnym stopniu zapewniają udogodnienia między językami asemblerowymi a językami wysokiego poziomu. Mogą być używane do wykonywania zadań, które wymagają bezpośredniego dostępu do urządzeń sprzętowych, ale nadal zapewniają struktury kontroli wyższego poziomu i sprawdzanie błędów.

Okres od lat sześćdziesiątych do późnych siedemdziesiątych XX wieku przyniósł rozwój najważniejszych obecnie używanych paradygmatów językowych:

Każdy z tych języków zrodził potomków, a większość współczesnych języków programowania zalicza przynajmniej jeden z nich do swoich przodków.

Lata sześćdziesiąte i siedemdziesiąte były również okresem poważnej debaty na temat zalet programowania strukturalnego oraz tego, czy języki programowania powinny być zaprojektowane tak, aby je wspierać. Edsger Dijkstra w słynnym liście z 1968 r. Opublikowanym w Komunikatach ACM argumentował, że instrukcje Goto powinny zostać wyeliminowane ze wszystkich języków programowania „wyższego poziomu”.

Konsolidacja i wzrost

Wybór podręczników do nauki programowania, w językach zarówno popularnych, jak i mało znanych. To tylko kilka z tysięcy języków programowania i dialektów, które zostały zaprojektowane w historii.

Lata osiemdziesiąte to lata względnej konsolidacji. C ++ łączy programowanie obiektowe i systemowe. Rząd Stanów Zjednoczonych ustandaryzował Ada , język programowania systemów wywodzący się z Pascala i przeznaczony do użytku przez wykonawców sektora obronnego. W Japonii i innych krajach wydano ogromne sumy na badanie tak zwanych języków „piątej generacji”, które zawierały konstrukcje programowania logicznego. Społeczność języków funkcjonalnych przeniosła się do standaryzacji ML i Lisp. Zamiast wymyślać nowe paradygmaty, wszystkie te ruchy rozwijały idee wymyślone w poprzednich dziesięcioleciach.

Jednym z ważnych trendów w projektowaniu języków do programowania systemów wielkoskalowych w latach 80. był zwiększony nacisk na wykorzystanie modułów lub jednostek organizacyjnych kodu na dużą skalę. Modula-2 , Ada i ML wszystkie opracowały godne uwagi systemy modułowe w latach 80., które często były związane z ogólnymi konstrukcjami programistycznymi .

Szybki rozwój Internetu w połowie lat 90. stworzył możliwości dla nowych języków. Perl , pierwotnie uniksowe narzędzie skryptowe wydane po raz pierwszy w 1987 roku, stał się powszechny w dynamicznych witrynach internetowych . Java zaczęła być używana do programowania po stronie serwera, a maszyny wirtualne z kodem bajtowym ponownie stały się popularne w środowisku komercyjnym z obietnicą „ Napisz raz, uruchom wszędzie ” ( UCSD Pascal był popularny przez pewien czas we wczesnych latach osiemdziesiątych). Rozwój ten nie był zasadniczo nowatorski; były raczej udoskonaleniami wielu istniejących języków i paradygmatów (chociaż ich składnia była często oparta na rodzinie języków programowania C).

Ewolucja języka programowania trwa, zarówno w przemyśle, jak iw badaniach. Aktualne kierunki obejmują weryfikację bezpieczeństwa i niezawodności , nowe rodzaje modułowości ( mieszanki , delegaci , aspekty ) oraz integrację baz danych, takich jak LINQ firmy Microsoft .

Języki programowania czwartej generacji (4GL) to języki programowania komputerów, których celem jest zapewnienie wyższego poziomu abstrakcji wewnętrznych szczegółów sprzętu komputerowego niż 3GL. Języki programowania piątej generacji (5GL) to języki programowania oparte na rozwiązywaniu problemów przy użyciu ograniczeń nadanych programowi, a nie przy użyciu algorytmu napisanego przez programistę.

Elementy

Wszystkie języki programowania mają pewne prymitywne bloki konstrukcyjne do opisu danych i zastosowanych do nich procesów lub transformacji (takich jak dodanie dwóch liczb lub wybór elementu z kolekcji). Te prymitywy są definiowane przez reguły składniowe i semantyczne, które opisują odpowiednio ich strukturę i znaczenie.

Składnia

Podświetlanie składni jest często używane, aby pomóc programistom w rozpoznawaniu elementów kodu źródłowego. Powyższy język to Python .

Forma powierzchni języka programowania jest znana jako jego składnia . Większość języków programowania jest czysto tekstowych; używają sekwencji tekstu, w tym słów, liczb i znaków interpunkcyjnych, podobnie jak pisane języki naturalne. Z drugiej strony, istnieją języki programowania, które mają bardziej graficzny charakter, wykorzystując wizualne relacje między symbolami w celu określenia programu.

Składnia języka opisuje możliwe kombinacje symboli, które tworzą program poprawny składniowo. Znaczenie nadane kombinacji symboli jest obsługiwane przez semantykę ( formalną lub zakodowaną na stałe w implementacji referencyjnej ). Ponieważ większość języków jest tekstowych, w tym artykule omówiono składnię tekstową.

Składnia języka programowania jest zwykle definiowana za pomocą kombinacji wyrażeń regularnych (dla struktury leksykalnej ) i formy Backus – Naur (dla struktury gramatycznej ). Poniżej znajduje się prosta gramatyka oparta na Lispie :

expression ::= atom | list
atom       ::= number | symbol
number     ::= [+-]?['0'-'9']+
symbol     ::= ['A'-'Z''a'-'z'].*
list       ::= '(' expression* ')'

Ta gramatyka określa, co następuje:

  • ekspresja jest albo atom lub lista ;
  • atom jest albo numer lub symbol ;
  • liczba jest nieprzerwany ciąg jednego lub większej liczby cyfr, ewentualnie poprzedzone znakiem plus lub minus;
  • symbolem jest litera następuje zero lub więcej dowolnych znaków (bez spacji); i
  • lista jest dopasowana para nawiasów, z zero lub więcej wyrażeń wewnątrz niego.

Poniżej przedstawiono przykłady z sensownych tokenów sekwencji w tym gramatyki: 12345 , () i (a b c232 (1)) .

Nie wszystkie programy poprawne składniowo są poprawne semantycznie. Mimo to wiele programów poprawnych składniowo jest źle sformułowanych, zgodnie z regułami języka; i może (w zależności od specyfikacji języka i poprawności implementacji) skutkować błędem w tłumaczeniu lub wykonaniu. W niektórych przypadkach takie programy mogą wykazywać niezdefiniowane zachowanie . Nawet jeśli program jest dobrze zdefiniowany w języku, nadal może mieć znaczenie, które nie jest zamierzone przez osobę, która go napisała.

Na przykładzie języka naturalnego może nie być możliwe przypisanie znaczenia poprawnemu gramatycznie zdaniu lub zdanie może być fałszywe:

Poniższy fragment języka C jest poprawny składniowo, ale wykonuje operacje, które nie są zdefiniowane semantycznie (operacja *p >> 4 nie ma znaczenia dla wartości o typie złożonym i p->im nie jest zdefiniowana, ponieważ wartość p jest pustym wskaźnikiem ):

complex *p = NULL;
complex abs_p = sqrt(*p >> 4 + p->im);

Jeśli deklaracja typu w pierwszej linii została pominięta, program wywołałby błąd na niezdefiniowanej zmiennej "p" podczas kompilacji. Jednak program nadal byłby poprawny składniowo, ponieważ deklaracje typu dostarczają tylko informacji semantycznych.

Gramatykę potrzebną do określenia języka programowania można sklasyfikować według jego pozycji w hierarchii Chomsky'ego . Składnię większości języków programowania można określić za pomocą gramatyki typu 2, tj. Są to gramatyki bezkontekstowe . Niektóre języki, w tym Perl i Lisp, zawierają konstrukcje, które umożliwiają wykonanie w fazie analizowania. Języki, które mają konstrukcje, które pozwalają programiście zmieniać zachowanie parsera, sprawiają, że analiza składniowa jest nierozstrzygalnym problemem i ogólnie zaciera różnicę między analizowaniem a wykonywaniem. W przeciwieństwie do systemu makr Lispa i BEGIN bloków Perla , które mogą zawierać ogólne obliczenia, makra C są jedynie zamiennikami ciągów i nie wymagają wykonywania kodu.

Semantyka

Termin semantyka odnosi się do znaczenia języków, a nie do ich formy ( składni ).

Semantyka statyczna

Semantyka statyczna określa ograniczenia dotyczące struktury prawidłowych tekstów, które są trudne lub niemożliwe do wyrażenia w standardowych formalizmach składniowych. W przypadku języków kompilowanych semantyka statyczna zasadniczo obejmuje te reguły semantyczne, które można sprawdzić w czasie kompilacji. Przykłady obejmują sprawdzenie, czy każdy identyfikator jest zadeklarowany przed jego użyciem (w językach, które wymagają takich deklaracji) lub czy etykiety na ramionach instrukcji case są różne. Wiele ważnych ograniczeń tego typu, takich jak sprawdzanie, czy identyfikatory są używane w odpowiednim kontekście (np. Nie dodawanie liczby całkowitej do nazwy funkcji) lub czy wywołania podprogramów mają odpowiednią liczbę i typ argumentów, można wymusić definiując je jako reguły w logice zwanej systemem typów . Inne formy analiz statycznych, takie jak analiza przepływu danych, również mogą być częścią semantyki statycznej. Nowsze języki programowania, takie jak Java i C #, mają określoną analizę przypisań , formę analizy przepływu danych, jako część ich statycznej semantyki.

Semantyka dynamiczna

Po określeniu danych należy poinstruować maszynę, aby wykonała operacje na danych. Na przykład semantyka może definiować strategię, za pomocą której wyrażenia są oceniane na wartości, lub sposób, w jaki struktury sterujące warunkowo wykonują instrukcje . W semantyka dynamiczne (znane również jako semantyki wykonania ) z A określa językowych jak i kiedy różne konstrukty języka powinna produkować zachowanie programu. Istnieje wiele sposobów definiowania semantyki wykonywania. Język naturalny jest często używany do określenia semantyki wykonania języków powszechnie używanych w praktyce. Znaczna część badań naukowych dotyczyła semantyki formalnej języków programowania , która umożliwia formalne określenie semantyki wykonania. Wyniki z tej dziedziny badań mają ograniczone zastosowanie do projektowania i wdrażania języków programowania poza środowiskiem akademickim.

System typów

System typów definiuje, w jaki sposób język programowania klasyfikuje wartości i wyrażenia na typy , jak może manipulować tymi typami i jak wchodzą w interakcje. Celem systemu typów jest weryfikacja i zazwyczaj wymuszanie pewnego poziomu poprawności w programach napisanych w tym języku poprzez wykrywanie pewnych nieprawidłowych operacji. Każdy system typów, który można rozstrzygnąć , wiąże się z kompromisem: odrzuca wiele niepoprawnych programów, ale może również zabronić niektórych poprawnych, aczkolwiek nietypowych programów. Aby ominąć tę wadę, wiele języków ma luki dotyczące typów , zwykle niezaznaczone rzutowania, które mogą być używane przez programistę do jawnego zezwalania na normalnie niedozwolone operacje między różnymi typami. W większości języków z typami system typów jest używany tylko do wpisywania programów sprawdzających , ale wiele języków, zwykle funkcjonalnych, wnioskuje o typy , zwalniając programistę od konieczności pisania adnotacji o typach. Formalne projektowanie i badanie systemów typów jest znane jako teoria typów .

Języki wpisane a nietypowe

Język jest wpisywany, jeśli specyfikacja każdej operacji definiuje typy danych, do których operacja ma zastosowanie. Na przykład dane reprezentowane przez "this text between the quotes" ciągiem znaków , aw wielu językach programowania podzielenie liczby przez ciąg nie ma znaczenia i nie zostanie wykonane. Niepoprawna operacja może zostać wykryta podczas kompilacji programu (sprawdzanie typu „statycznego”) i zostanie odrzucona przez kompilator z komunikatem o błędzie kompilacji lub może zostać wykryta podczas działania programu („dynamiczne” sprawdzanie typu), co skutkuje w wyjątku czasu wykonywania . Wiele języków pozwala funkcji zwanej procedurą obsługi wyjątków na obsługę tego wyjątku i, na przykład, zawsze zwraca „-1” jako wynik.

Szczególnym przypadkiem języków z typami są języki z pojedynczym typem . Są to często języki skryptowe lub języki znaczników, takie jak REXX lub SGML , i mają tylko jeden typ danych - najczęściej są to ciągi znaków, które są używane zarówno dla danych symbolicznych, jak i liczbowych.

W przeciwieństwie do tego język bez typu , taki jak większość języków asemblera , pozwala na wykonanie dowolnej operacji na dowolnych danych, generalnie na sekwencjach bitów o różnej długości. Beztypowe języki wysokiego poziomu obejmują BCPL , Tcl i niektóre odmiany Forth .

W praktyce, podczas gdy kilka języków uważa się za wpisane na podstawie teorii typów (weryfikacja lub odrzucenie wszystkich operacji), większość współczesnych języków oferuje pewien stopień pisania. Wiele języków produkcyjnych zapewnia środki do ominięcia lub podważenia systemu typów, handlując bezpieczeństwem typów dla dokładniejszej kontroli nad wykonywaniem programu (zobacz rzutowanie ).

Pisanie statyczne a dynamiczne

W typowaniu statycznym wszystkie wyrażenia mają swoje typy określone przed wykonaniem programu, zwykle w czasie kompilacji. Na przykład 1 i (2 + 2) są wyrażeniami całkowitymi; nie można ich przekazać do funkcji, która oczekuje ciągu znaków, ani przechowywać w zmiennej zdefiniowanej do przechowywania dat.

Języki z typami statycznymi mogą być jawnie wpisane lub wywnioskowane o typie . W pierwszym przypadku programista musi jawnie pisać typy w określonych pozycjach tekstowych (na przykład w deklaracjach zmiennych ). W drugim przypadku kompilator wnioskuje typy wyrażeń i deklaracji na podstawie kontekstu. Większość popularnych języków z typowaniem statycznym, takich jak C ++ , C # i Java , jest wyraźnie wpisywana. Pełne wnioskowanie o typie tradycyjnie kojarzy się z mniej popularnymi językami, takimi jak Haskell i ML . Jednak wiele języków z jawną typizacją obsługuje częściowe wnioskowanie o typie; na przykład C ++ , Java i C # wszystkie wnioskują o typach w pewnych ograniczonych przypadkach. Ponadto niektóre języki programowania pozwalają na automatyczną konwersję niektórych typów na inne; na przykład int może być używany tam, gdzie program oczekuje liczby zmiennoprzecinkowej.

Typowanie dynamiczne , zwane także typowaniem ukrytym , określa bezpieczeństwo operacji w czasie wykonywania; innymi słowy, typy są skojarzone z wartościami czasu wykonywania, a nie z wyrażeniami tekstowymi . Podobnie jak w przypadku języków opartych na typie, języki dynamicznie typowane nie wymagają od programisty pisania jawnych adnotacji typu w wyrażeniach. Między innymi może to pozwolić pojedynczej zmiennej na odwoływanie się do wartości różnych typów w różnych punktach wykonywania programu. Jednak błędów typu nie można automatycznie wykryć, dopóki fragment kodu nie zostanie faktycznie wykonany, co może utrudnić debugowanie . Lisp , Smalltalk , Perl , Python , JavaScript i Ruby to przykłady języków dynamicznie typowanych.

Słabe i mocne pisanie

Słabe wpisywanie umożliwia traktowanie wartości jednego typu jako innej, na przykład traktowanie ciągu znaków jako liczby. Czasami może to być przydatne, ale może również pozwolić, aby niektóre rodzaje błędów programu pozostały niewykryte w czasie kompilacji, a nawet w czasie wykonywania .

Silne pisanie zapobiega tym błędom programu. Próba wykonania operacji na niewłaściwym typie wartości powoduje błąd. Języki z silną typizacją są często określane jako bezpieczne dla typów lub bezpieczne .

Alternatywna definicja „słabo wpisanych” odnosi się do języków, takich jak Perl i JavaScript , które pozwalają na dużą liczbę niejawnych konwersji typów. W JavaScript, na przykład, wyrażenie 2 * x niejawnie konwertuje x do numeru, a to konwersja powiedzie się, nawet jeśli x jest null , undefined An Array , lub ciąg liter. Takie niejawne konwersje są często przydatne, ale mogą maskować błędy programowania. Silne i statyczne są obecnie ogólnie uważane za koncepcje ortogonalne, ale ich użycie w literaturze jest inne. Niektórzy używają terminu silnie typowany, aby oznaczać silnie typowany statycznie lub, co jest jeszcze bardziej mylące, po prostu typowany statycznie . Tak więc C został nazwany zarówno silnie typizowany, jak i słabo typizowany statycznie.

Niektórym profesjonalnym programistom może wydawać się dziwne, że C może być napisane „słabo, statycznie”. Należy jednak zauważyć, że użycie wskaźnika ogólnego, void * pointer, umożliwia rzutowanie wskaźników na inne wskaźniki bez konieczności wykonywania jawnego rzutowania. Jest to bardzo podobne do rzutowania tablicy bajtów na dowolny typ danych w C bez użycia jawnego rzutowania, takiego jak (int) lub (char) .

Biblioteka standardowa i system wykonawczy

Większość języków programowania ma powiązaną bibliotekę podstawową (czasami nazywaną „biblioteką standardową”, zwłaszcza jeśli jest zawarta jako część opublikowanego standardu językowego), która jest konwencjonalnie udostępniana przez wszystkie implementacje języka. Biblioteki podstawowe zazwyczaj zawierają definicje powszechnie używanych algorytmów, struktur danych oraz mechanizmów wprowadzania i wyprowadzania.

Granica między językiem a jego podstawową biblioteką różni się w zależności od języka. W niektórych przypadkach projektanci języka mogą traktować bibliotekę jako odrębną całość od języka. Jednak podstawowa biblioteka języka jest często traktowana przez użytkowników jako część języka, a niektóre specyfikacje języka wymagają nawet, aby ta biblioteka była dostępna we wszystkich implementacjach. Rzeczywiście, niektóre języki są zaprojektowane w taki sposób, że znaczenia pewnych konstrukcji składniowych nie mogą być nawet opisane bez odniesienia do biblioteki podstawowej. Na przykład w języku Java literał łańcuchowy jest definiowany jako instancja java.lang.String klasy; Podobnie w Smalltalk , anonimowa funkcja wyrażenie (a „blok”) tworzy instancję biblioteki BlockContext klasy. I odwrotnie, Scheme zawiera wiele spójnych podzbiorów, które wystarczają do skonstruowania reszty języka jako makr bibliotecznych, więc projektanci języka nawet nie zadają sobie trudu, aby powiedzieć, które części języka muszą być zaimplementowane jako konstrukcje językowe, a które muszą być zaimplementowane jako części biblioteki.

Projektowanie i wdrażanie

Języki programowania mają wspólne właściwości z językami naturalnymi, które są związane z ich przeznaczeniem jako wehikułami komunikacji, mają formę składniową niezależną od semantyki i pokazują rodziny języków pokrewnych, rozgałęziających się między sobą. Ale jako sztuczne konstrukcje różnią się one również w fundamentalny sposób od języków, które wyewoluowały w wyniku użycia. Istotna różnica polega na tym, że język programowania można w pełni opisać i zbadać w całości, ponieważ ma precyzyjną i skończoną definicję. Z kolei języki naturalne mają zmieniające się znaczenia nadawane przez ich użytkowników w różnych społecznościach. Chociaż języki konstruowane są również językami sztucznymi, zaprojektowanymi od podstaw w określonym celu, brakuje im precyzyjnej i kompletnej definicji semantycznej, jaką ma język programowania.

Wiele języków programowania zostało zaprojektowanych od podstaw, dostosowanych do nowych potrzeb i połączonych z innymi językami. Wiele z nich ostatecznie wyszło z użycia. Chociaż podejmowano próby zaprojektowania jednego „uniwersalnego” języka programowania, który służy wszystkim celom, żaden z nich nie został ogólnie zaakceptowany jako spełniający tę rolę. Potrzeba różnorodnych języków programowania wynika z różnorodności kontekstów, w których języki są używane:

  • Programy obejmują zarówno małe skrypty napisane przez indywidualnych hobbystów, jak i ogromne systemy napisane przez setki programistów .
  • Programiści mają wiedzę specjalistyczną od nowicjuszy, którzy potrzebują przede wszystkim prostoty, po ekspertów, którzy mogą czuć się komfortowo ze znaczną złożonością.
  • Programy muszą równoważyć szybkość, rozmiar i prostotę w systemach, od mikrokontrolerów po superkomputery .
  • Programy mogą być napisane raz i nie mogą być zmieniane przez pokolenia lub mogą podlegać ciągłym modyfikacjom.
  • Programiści mogą po prostu różnić się upodobaniami: mogą być przyzwyczajeni do omawiania problemów i wyrażania ich w określonym języku.

Jednym z powszechnych trendów w rozwoju języków programowania było dodawanie większej zdolności do rozwiązywania problemów przy użyciu wyższego poziomu abstrakcji . Najwcześniejsze języki programowania były bardzo ściśle powiązane z podstawowym sprzętem komputera. Wraz z rozwojem nowych języków programowania dodano funkcje, które pozwalają programistom wyrażać pomysły, które są bardziej odległe od prostego tłumaczenia na podstawowe instrukcje sprzętowe. Ponieważ programiści są mniej przywiązani do złożoności komputera, ich programy mogą wykonywać więcej obliczeń przy mniejszym wysiłku ze strony programisty. To pozwala im napisać więcej funkcji w jednostce czasu.

Programowanie w języku naturalnym zostało zaproponowane jako sposób na wyeliminowanie potrzeby stosowania specjalistycznego języka do programowania. Jednak cel ten pozostaje odległy, a wynikające z niego korzyści są przedmiotem dyskusji. Edsger W. Dijkstra stanął na stanowisku, że użycie języka formalnego jest niezbędne, aby zapobiec wprowadzaniu bezsensownych konstrukcji, i odrzucił programowanie w języku naturalnym jako „głupie”. Alan Perlis również odrzucił ten pomysł. Podejścia hybrydowe zostały zastosowane w strukturalnym języku angielskim i SQL .

Projektanci i użytkownicy języka muszą skonstruować szereg artefaktów, które regulują i umożliwiają praktykę programowania. Najważniejsze z tych artefaktów to specyfikacja i implementacja języka .

Specyfikacja

Specyfikacja języka programowania jest artefaktem, który użytkownicy języka i osoby wdrażające mogą wykorzystać, aby uzgodnić, czy fragment kodu źródłowego jest prawidłowym programem w tym języku, a jeśli tak, to jakie powinno być jego zachowanie.

Specyfikacja języka programowania może przybierać różne formy, w tym następujące:

Realizacja

Implementacja języka programowania zapewnia sposób pisania programów w tym języku i wykonać je na jednym lub wielu konfiguracjach sprzętu i oprogramowania. Ogólnie rzecz biorąc, istnieją dwa podejścia do implementacji języka programowania: kompilacja i interpretacja . Generalnie możliwe jest zaimplementowanie języka przy użyciu dowolnej techniki.

Dane wyjściowe kompilatora mogą być wykonywane przez sprzęt lub program zwany interpreter. W niektórych implementacjach, które wykorzystują podejście interpretera, nie ma wyraźnej granicy między kompilacją a interpretacją. Na przykład niektóre implementacje języka BASIC kompilują, a następnie wykonują źródło po jednym wierszu.

Programy uruchamiane bezpośrednio na sprzęcie zwykle działają znacznie szybciej niż te, które są interpretowane programowo.

Jedną z technik poprawy wydajności zinterpretowanych programów jest kompilacja just in time . Tutaj maszyna wirtualna , tuż przed wykonaniem, tłumaczy bloki kodu bajtowego, które mają zostać użyte, na kod maszynowy w celu bezpośredniego wykonania na sprzęcie.

Języki zastrzeżone

Chociaż większość najczęściej używanych języków programowania ma w pełni otwarte specyfikacje i implementacje, wiele języków programowania istnieje tylko jako zastrzeżone języki programowania z implementacją dostępną tylko od jednego dostawcy, który może twierdzić, że taki zastrzeżony język jest ich własnością intelektualną. Zastrzeżone języki programowania to zwykle języki specyficzne dla domeny lub wewnętrzne języki skryptowe dla pojedynczego produktu; niektóre zastrzeżone języki są używane tylko wewnętrznie w ramach dostawcy, podczas gdy inne są dostępne dla użytkowników zewnętrznych.

Niektóre języki programowania istnieją na pograniczu prawnie zastrzeżonych i otwartych; na przykład, Oracle Corporation twierdzi prawa własności do niektórych aspektów języka programowania Java , a Microsoft jest C # język programowania, który ma otwarte implementacje większości części systemu, ma również Common Language Runtime (CLR) w zamkniętym środowisku.

Wiele języków zastrzeżonych jest powszechnie używanych, pomimo ich zastrzeżonego charakteru; przykłady obejmują MATLAB , VBScript i Wolfram Language . W niektórych językach może nastąpić przejście od zamkniętego do otwartego; na przykład Erlang był pierwotnie wewnętrznym językiem programowania firmy Ericsson.

Posługiwać się

Powstały tysiące różnych języków programowania, głównie w dziedzinie informatyki. Poszczególne projekty oprogramowania zwykle używają pięciu lub więcej języków programowania.

Języki programowania różnią się od większości innych form ludzkiej ekspresji tym, że wymagają większej precyzji i kompletności. Używając języka naturalnego do komunikowania się z innymi ludźmi, ludzcy autorzy i użytkownicy mogą być niejednoznaczni i popełniać drobne błędy, a jednocześnie oczekiwać, że ich intencje zostaną zrozumiane. Jednak mówiąc obrazowo, komputery „robią dokładnie to, co im każą” i nie mogą „zrozumieć”, jaki kod zamierzał napisać programista. Połączenie definicji języka, programu i danych wejściowych programu musi w pełni określać zewnętrzne zachowanie, które występuje, gdy program jest wykonywany, w domenie kontroli tego programu. Z drugiej strony pomysły dotyczące algorytmu można przekazać ludziom bez precyzji wymaganej do wykonania za pomocą pseudokodu , który przeplata język naturalny z kodem napisanym w języku programowania.

Język programowania zapewnia ustrukturyzowany mechanizm definiowania fragmentów danych oraz operacji lub transformacji, które mogą być wykonywane automatycznie na tych danych. Programista używa abstrakcje przedstawienia w języku do reprezentowania pojęć zaangażowane w obliczeniach. Pojęcia te są reprezentowane jako zbiór najprostszych dostępnych elementów (zwanych prymitywami ). Programowanie to proces, w którym programiści łączą te prymitywy, aby tworzyć nowe programy lub dostosowywać istniejące do nowych zastosowań lub zmieniającego się środowiska.

Programy dla komputera mogą być wykonywane w procesie wsadowym bez udziału człowieka, czy użytkownik może wpisać komendy w sesji interaktywnej wystąpienia tłumacza . W tym przypadku „polecenia” to po prostu programy, których wykonanie jest powiązane ze sobą. Gdy język może uruchamiać swoje polecenia za pośrednictwem interpretera (takiego jak powłoka systemu Unix lub inny interfejs wiersza poleceń ) bez kompilacji, nazywa się go językiem skryptowym .

Pomiar użycia języka

Określenie, który jest najczęściej używanym językiem programowania, jest trudne, ponieważ definicja użycia różni się w zależności od kontekstu. Jeden język może zajmować większą liczbę godzin programisty, inny ma więcej linii kodu, a trzeci może pochłaniać najwięcej czasu procesora. Niektóre języki są bardzo popularne w określonych rodzajach aplikacji. Na przykład COBOL jest nadal silny w korporacyjnych centrach danych, często na dużych komputerach mainframe ; Fortran w zastosowaniach naukowych i inżynieryjnych; Ada w zastosowaniach lotniczych, transportowych, wojskowych, czasu rzeczywistego i wbudowanych; i C w aplikacjach wbudowanych i systemach operacyjnych. Inne języki są regularnie używane do pisania wielu różnych rodzajów aplikacji.

Zaproponowano różne metody pomiaru popularności języka, z których każda wiąże się z innym nastawieniem do tego, co jest mierzone:

  • liczenie ogłoszeń o pracę, które wspominają o języku
  • liczba sprzedanych książek, które uczą lub opisują język
  • szacunki liczby istniejących wierszy kodu napisanych w danym języku - co może nie doceniać języków rzadko spotykanych w publicznych wyszukiwaniach
  • liczba odniesień do języka (tj. do nazwy języka) znalezionych za pomocą wyszukiwarki internetowej.

Łącząc i uśredniając informacje z różnych witryn internetowych, stackify.com podał dziesięć najpopularniejszych języków programowania jako (w porządku malejącym według ogólnej popularności): Java , C , C ++ , Python , C # , JavaScript , VB .NET , R , PHP i MATLAB .

Dialekty, smaki i implementacje

Dialekt języka programowania lub języka wymiany danych jest (stosunkowo małe) zmianę lub rozszerzenie języka, który nie zmienia swojej wewnętrznej natury. W przypadku języków takich jak Scheme i Forth , standardy mogą być uważane przez wykonawców za niewystarczające, nieodpowiednie lub niezgodne z prawem, więc często odbiegają od standardu, tworząc nowy dialekt . W innych przypadkach dialekt jest tworzony do użytku w języku specyficznym dla domeny , często w podzbiorze. W świecie Lispa większość języków, które używają podstawowej składni S-wyrażeń i semantyki podobnej do Lispa, są uważane za dialekty Lispa, chociaż różnią się one znacznie, podobnie jak, powiedzmy, Racket i Clojure . Ponieważ jeden język ma wiele dialektów, niedoświadczonym programistom może być dość trudno znaleźć odpowiednią dokumentację. Język programowania BASIC ma wiele dialektów .

Eksplozja dialektów Forth doprowadziła do powiedzenia „Jeśli widziałeś jednego Fortha ... widziałeś jednego Forth”.

Taksonomie

Nie ma nadrzędnego schematu klasyfikacji języków programowania. Dany język programowania zwykle nie ma ani jednego języka przodka. Języki powstają powszechnie, łącząc elementy kilku wcześniejszych języków z nowymi ideami będącymi w obiegu w tamtym czasie. Pomysły, które pochodzą z jednego języka, rozprzestrzenią się w rodzinie pokrewnych języków, a następnie nagle przeskoczą przez luki rodzinne, by pojawić się w zupełnie innej rodzinie.

Zadanie dodatkowo komplikuje fakt, że języki można klasyfikować wzdłuż wielu osi. Na przykład Java jest zarówno językiem zorientowanym obiektowo (ponieważ zachęca do organizacji zorientowanej obiektowo), jak i językiem współbieżnym (ponieważ zawiera wbudowane konstrukcje do równoległego uruchamiania wielu wątków ). Python to obiektowy język skryptowy .

Mówiąc ogólnie , języki programowania dzielą się na paradygmaty programowania i klasyfikację według zamierzonej dziedziny użycia, z językami programowania ogólnego przeznaczenia odróżnionymi od języków programowania specyficznych dla domeny . Tradycyjnie języki programowania były traktowane jako opisujące obliczenia w kategoriach zdań rozkazujących, czyli wydawania poleceń. Nazywa się je ogólnie imperatywnymi językami programowania . Wiele badań w językach programowania miało na celu zatarcie różnicy między programem jako zbiorem instrukcji a programem jako stwierdzeniem o pożądanej odpowiedzi, co jest główną cechą programowania deklaratywnego . Bardziej wyrafinowane paradygmaty obejmują programowanie proceduralne , programowanie obiektowe , programowanie funkcjonalne i programowania logicznego ; niektóre języki są hybrydami paradygmatów lub wieloparadygmatycznymi. Asemblera jest nie tyle paradygmat jako bezpośredni modelu bazowego architektury maszyny. Celowo, języki programowania można uznać za języki ogólnego przeznaczenia, języki programowania systemu, języki skryptowe, języki specyficzne dla domeny lub języki współbieżne / rozproszone (lub ich kombinację). Niektóre języki ogólnego przeznaczenia zostały zaprojektowane głównie z myślą o celach edukacyjnych.

Język programowania można również sklasyfikować według czynników niezwiązanych z paradygmatem programowania. Na przykład większość języków programowania używa słów kluczowych w języku angielskim , podczas gdy mniejszość tego nie robi . Inne języki można sklasyfikować jako celowo ezoteryczne lub nie.

Zobacz też

Bibliografia

Dalsza lektura

Linki zewnętrzne