Dynamiczny język programowania
- Ten artykuł dotyczy klasy języków programowania. Metoda na zmniejszanie złożoności obliczeniowej algorytmów o podobnej nazwie opisana jest w artykule Programowanie dynamiczne.
Dynamiczny język programowania jest terminem powszechnie używanym w informatyce oznaczającym klasę języków programowania wysokiego poziomu, które podczas działania programu wykonują wiele operacji przeprowadzanych w innych językach na etapie kompilacji. Do tych działań zalicza się na przykład rozszerzanie programu przez dodawanie nowego kodu, przez rozszerzanie obiektów i definicji, albo przez zmianę typów danych – wszystko podczas działania programu. Zachowania takie można emulować w niemal wszystkich językach programowania o wystarczającej złożoności, jednak języki dynamiczne mają wbudowane konstrukcje umożliwiające ich bezpośrednie wykorzystanie.
Języki dynamiczne i dynamiczne typowanie nie są tożsamymi pojęciami, a dynamiczny język programowania nie musi zawsze posiadać mechanizmu dynamicznej zmiany typów, chociaż w praktyce wiele z takich języków obsługuje tę właściwość.
Ograniczenia i wieloznaczności definicji[edytuj | edytuj kod]
Definicja języka dynamicznego jest wieloznaczna, ponieważ próbuje się w niej dokonać rozróżnienia na kod i dane, podobnie jak na kompilację i uruchamianie, chociaż pojęcia te nie mają uniwersalnego znaczenia. Maszyny wirtualne, just-in-time compilation i zdolność wielu języków programowania do bezpośrednich modyfikacji kodu maszynowego w niektórych systemach, czynią wspomniane rozróżnienia bardzo abstrakcyjnymi. Na ogólnym poziomie, założenie, że język jest dynamiczny, jest naprawdę założeniem odnośnie do łatwego korzystania z dynamicznych mechanizmów, bardziej niż precyzyjnym określeniem możliwości danego języka.
Implementacje[edytuj | edytuj kod]
Istnieje kilka mechanizmów wynikających z koncepcji programowania dynamicznego. Żaden z nich nie może być podstawą do sklasyfikowania języka jako dynamicznego, chociaż większość można znaleźć wśród tych języków.
Eval[edytuj | edytuj kod]
Konstrukcja eval została wprowadzona w języku programowania Lisp i oznaczała ewaluację wyrażenia, czyli proces wykonywania instrukcji umieszczonych w strukturze danych zwanej tam wyrażeniem symbolicznym. Nowe znaczenie tego terminu odnosi się do mechanizmu lub procesu polegającego na wykonywaniu dowolnych instrukcji umieszczonych w łańcuchach tekstowych lub innych danych niebędących kodem maszynowym, do których program ma dostęp. Ewaluacja nowego kodu programu jest częstym zjawiskiem w wielu nowych językach programowania, które w przeciwieństwie do Lispa, nie wymagają od programisty rozróżniania procesu wczytywania łańcucha znaków i przekształcania go do postaci zinternalizowanej w celu wykonania na nim dalszych działań. Języki te to głównie języki interpretowane, gdzie z ewaluacją mamy w gruncie rzeczy do czynienia podczas każdorazowego wczytywania kodu w celu uruchomienia.
Funkcje wyższego rzędu[edytuj | edytuj kod]
Erik Meijer i Peter Drayton zwracają uwagę, że każdy język programowania, w którym możliwe jest ładowanie kodu wykonywalnego podczas pracy programu jest w pewnym sensie zdolny do wykonywania ewaluacji, nawet jeśli kod ten jest w postaci dynamicznie ładowanej biblioteki współdzielonej lub maszynowej formy zrozumiałej przez procesor. Sugerują oni, że tak naprawdę dopiero obecność funkcji wyższego rzędu jest wyznacznikiem pozwalającym nazwać język dynamicznym, a niektóre z języków używają konstrukcji eval tylko jako ubogiej namiastki funkcji wyższego rzędu[1]
Zmiana obiektów podczas pracy[edytuj | edytuj kod]
W języku dynamicznym typy danych lub system obiektów mogą być modyfikowane podczas działania programu. Może to oznaczać tworzenie nowych typów i obiektów o właściwościach wynikających z wyników umieszczonych w programie wyrażeń, albo spowodowanych użyciem domieszek istniejących obiektów i typów. Zmiana obiektów ma również miejsce podczas procesu dziedziczenia lub drzewiastego odwzorowywania typów, czyli zmiany zachowania zdefiniowanych już typów danych (ze szczególnym uwzględnieniem wywoływanych metod).
Programowanie funkcyjne[edytuj | edytuj kod]
Koncepcje znane z programowania funkcyjnego zaimplementowano w wielu dynamicznych językach programowania. One również pochodzą z języka Lisp.
Domknięcia[edytuj | edytuj kod]
Jednym z najpowszechniej używanych konstrukcji programowania funkcyjnego występujących w dynamicznych językach są domknięcia. Umożliwiają one tworzenie nowych instancji funkcji, które jednak nie tracą dostępu do danych kontekstu, w którym zostały utworzone. Prostym przykładem może być stworzenie funkcji służącej do wyszukiwania słowa w tekście:
function nowy_skaner (słowo) temp_function = function (wejście) szukaj_słowa (wejście, słowo) end function return temp_function end function
Zauważ, że wewnętrzna funkcja jest anonimowa (nie ma nazwy), a miejscem jej przechowywania jest zmienna temp_function
. Za każdym razem, gdy wywoływana jest funkcja nowy_skaner()
, zwracana przez nią będzie nowa funkcja, która pamięta wartość przekazanego jej podczas definiowania argumentu słowo
.
Domknięcia[2] są jednym z głównych narzędzi programowania funkcyjnego, a wiele języków obsługuje mechanizmy tego programowania przynajmniej na tym poziomie.
Kontynuacje[edytuj | edytuj kod]
Kolejną cechą niektórych języków dynamicznych jest mechanizm kontynuacji. Konstrukcje kontynuacyjne pozwalają odzwierciedlić stan wykonywania się programu, który może być potem ponownie wywołany. Na przykład parser może zwracać wynik pośredni i kontynuację, która po wywołaniu sprawi, że przetwarzanie danych wejściowych będzie dalej prowadzone. Kontynuacje wpływają na to, jak traktowane są zasięgi zmiennych, funkcji i metod, ze szczególnym naciskiem na tzw. domknięcia. Ich użycie wymaga czujności programisty i ostrożności podczas implementowania przez twórców języka. Z tego powodu wiele języków dynamicznych nie obsługuje kontynuacji.
Mechanizm refleksji[edytuj | edytuj kod]
Refleksja jest cechą wielu dynamicznych języków i zazwyczaj wiąże się z ogólnym procesem analizy typów i metadanych lub polimorfizmem danych. Może ona również oznaczać pełną ewaluację i modyfikację kodu programu reprezentowanego w strukturach danych, tak jak to ma miejsce w wyrażeniach symbolicznych języka Lisp.
Makra[edytuj | edytuj kod]
Pewna ograniczona liczba dynamicznych języków programowania udostępnia mechanizmy, w których ewaluacja i introspekcja kodu łączą się w konstrukcję zwaną makrem. Większość programistów zna ten termin i używało makrodefinicji na przykład w języku C czy C++, gdzie pozwalają one na dokonywanie prostych podstawień łańcuchów stanowiących kod programu. W językach dynamicznych makra umożliwiają dostęp do wewnętrznych struktur kompilatora i pełny dostęp do interpretera, maszyny wirtualnej lub środowiska uruchomieniowego. W ten sposób programista jest w stanie wpływać na procesy związane z optymalizacją kodu i modyfikować składnię i gramatykę używanego języka.
Języki[edytuj | edytuj kod]
- APL
- BeFunge
- C# (≥4.0)
- ChucK
- ColdFusion
- CURL
- D
- DBL
- ECMAScript
- Eiffel (język programowania)
- Erlang (język programowania)
- Forth
- Groovy
- HyperCard/HyperTalk i pochodne
- Io
- Lisp
- Logtalk
- Lua
- Maude system
- MUMPS
- Oberon
- Objective Modula-2
- Objective-C
- Perl
- PHP
- Pliant
- POP-11
- Poplog
- Pike
- Prolog
- Python
- R
- REALbasic
- REBOL
- Ruby
- Scala
- Scratch
- Smalltalk
- Snobol
- SuperCollider
- Tcl
- język makr systemu TeX
- VBScript
- Visual Basic 9 lub 10
- Visual FoxPro
- Windows PowerShell
- xHarbour
Asembler, język C, C++, wczesne wydania Javy, a także FORTRAN nie są językami dynamicznymi.
Przypisy[edytuj | edytuj kod]
- ↑ Meijer, Erik i Peter Drayton: Static Typing Where Possible, Dynamic Typing When Needed: The End of the Cold War Between Programming Languages. Microsoft Corporation, 2005.
- ↑ Obejrzyj przykład użycia na str. 330 książki Larry'ego Walla pt. Programming Perl ISBN 0-596-00027-8
Linki zewnętrzne[edytuj | edytuj kod]
- Dynamic Languages—ready for the next challenges, by design, David Ascher, PhD; ActiveState, July 27, 2004.