Динамички програмски језик је термин који се користи у рачунарској науци да опише класу програмских језика на високом нивоу које, компоненте, извршавају многа заједничка програмска понашања која статички програмски језици врше током компилације. Ова понашања могу укључивати продужење програма, додајући нову шифру, проширујући објекте и дефиниције, или модификација типа система. Иако слична понашања могу емулирати у готово било ком језику, уз различите степене тежине, сложености и перформанси трошкова, динамички језици дају директне алате да искористе од њих. Многе од ових функција су прво имплементиране као матерње функције у Lisp програмском језику.
Најдинамичнија језици су такође динамички откуцани, али нису сви. Динамички језици се често (али не увек) називају "скрипт језици", иако се термин "скрипт језик" у најужем смислу односи на језике који су специфични за дато компонентно окружењу.
Имплементација
Евал
Неки динамички језици нуде евал функцију. Ова функција узима параметар стринг који садржи код у језику, и извршава га. Ако је овај код скраћеница за израз, добијена вредност се враћа. Међутим, Ерик Меијер и Петер Драитон указују на то да програмери "користе евал као сиромашну човек замену за функције вишег реда."[1]
Објекат компонентна промена
Врста објекта или система може обично да се мења у току извршавања у динамичном језику. То може да значи стварање нових објеката из дефиниције компоненте или на основу mixins постојећих врста или објеката. То такође може да се односи на промену наследства или типа дрва, и на тај начин мењајући начин на који се постојећи типове понашају (посебно у односу на позивање метода).
Функционално програмирање
Функционални програмски концепти су карактеристика многих динамичких језика, а такође произилазе из Lisp.
Затварање
Један од најчешће коришћених аспеката функционалног програмирања у динамичким језицима је затварање, који омогућава креирање нове инстанце функције које задржава приступ контекста у коме је настала. Једноставан пример за то је стварање функција за скенирање текста за речи:
function нови скенер (реч)
temp_function = function (улазни)
скенирање за текст (улазно, реч)
end functionreturn temp_function
end function
Ваља имати на уму да унутрашња функција нема име, а уместо тога чува у променљивој temp_function-и. Сваки пут new_scanner се извршава, он ће вратити нову функцију која памти вредност речи параметара који су усвојени када је дефинисан.
Затварање[2] је један од кључних инструмената функционалног програмирања, а многи језици подржавају најмање овај степен функционалног програмирања.
Наставак
Друга карактеристика неких динамичких језика је наставак. Наставака представља извршење стања које се могу поново позвати. На пример, анализатор може да врати средњи резултат и наставак који, када се позове, ће наставити да анализира улаз. Наставак комуницира у веома сложеним начинима за одређивање оквира, посебно у погледу затварања. Из тог разлога, многи динамички језици не дају наставке.
Одраз
Одраз је уобичајен у многим динамичким језицима, и обично укључује анализу типова и метаподатака генеричких или полиморфних података. То, међутим, такође укључује пуну процену и модификацију програмског кода податка, као што су функције које пружа Lisp, у анализи С-израза.
Макрои
Ограничен број динамичких програмским језика пружа могућности које комбинују код интроспекције (способност да испита класе, функције и кључне речи да знају шта су, шта раде и шта знају) и евал под називом макрои. Већина програмера данас који су свесни термина макро срели су га у C или C++, где су статичне карактеристике које се уграђују у мали подскупу језика, и да су способне само за стринг замене на тексту програма. У динамичким језицима, међутим, они дају приступ унутрашњим пословима преводиоца и пуни приступ преводиоцу, виртуелне машине, или компоненти, која омогућава дефинисање језика налик конструкцији која може оптимизирати код или модификује синтаксу или граматику језика.
Обрачунавање кода на издржљивости и касно везивање
Пример показује како се функција може мењати у току рада из обрачунатог изворног кода
; изворни код се чува као података у променљивојCL-USER>(defparameter*best-guess-formula*'(lambda(x)(*xx2.5)))*BEST-GUESS-FORMULA*; функција је створен од кода и састављена у току рада, функција је доступан под именом најбољи-гуессCL-USER>(compile'best-guess*best-guess-formula*)#<Function1540600152F4>; функција се може назватиCL-USER>(best-guess10.3)265.225; изворни код може бити побољшан у току радаCL-USER>(setf*best-guess-formula*`(lambda(x),(list'sqrt(third*best-guess-formula*))))(LAMBDA(X)(SQRT(*XX2.5))); нова верзија функције се састављаCL-USER>(compile'best-guess*best-guess-formula*)#<Function16406000085C>; следећи позив ће позвати нову функцију, функцију у последње време везивањаCL-USER>(best-guess10.3)16.28573
Објекат компонентна промена
Овај пример показује како се постојећи пример мења укључујући нови слот кад се класа промени и да се постојећи начин може заменити са новом верзијом.
; особа класа. Особа има име.CL-USER>(defclassperson()((name:initarg:name)))#<STANDARD-CLASSPERSON4020081FB3>; обичај штампања метода за објекте класе особеCL-USER>(defmethodprint-object((pperson)stream)(print-unreadable-object(pstream:typet)(formatstream"~a"(slot-valuep'name))))#<STANDARD-METHODPRINT-OBJECTNIL(PERSONT)4020066E5B>; један пример особа инстанцаCL-USER>(setf*person-1*(make-instance'person:name"Eva Luator"))#<PERSONEvaLuator>; класа особа добија други слот. Она тада има назив слот и старост.CL-USER>(defclassperson()((name:initarg:name)(age:initarg:age:initform:unknown)))#<STANDARD-CLASSPERSON4220333E23>; ажурирање метода за штампање објекатCL-USER>(defmethodprint-object((pperson)stream)(print-unreadable-object(pstream:typet)(formatstream"~a age: ~"(slot-valuep'name)(slot-valuep'age))))#<STANDARD-METHODPRINT-OBJECTNIL(PERSONT)402022ADE3>; постојећи објекат се сада променио, она има додатни слот и нови метод за штампањеCL-USER>*person-1*#<PERSONEvaLuatorage:UNKNOWN>; можемо поставити ново доба слот за примерCL-USER>(setf(slot-value*person-1*'age)25)25; објекат је ажуриранCL-USER>*person-1*#<PERSONEvaLuatorage:25>
Склапање кода компонентне основе на класи случајева
У следећем примеру класа особа добија нову суперкласу. Метод за штампање је редефинисана тако да окупља неколико метода у ефективном методу. Ефективна метода је монтирана на основу класе аргумента и компонента на располагању и важећим методама.
; класа особаCL-USER>(defclassperson()((name:initarg:name)))#<STANDARD-CLASSPERSON4220333E23>; особа само исписује своје имеCL-USER>(defmethodprint-object((pperson)stream)(print-unreadable-object(pstream:typet)(formatstream"~a"(slot-valuep'name))))#<STANDARD-METHODPRINT-OBJECTNIL(PERSONT)40200605AB>; особа инстанцаCL-USER>(defparameter*person-1*(make-instance'person:name"Eva Luator"))*PERSON-1*; приказује особу инстанцуCL-USER>*person-1*#<PERSONEvaLuator>; сада редефинисање начина штампања да би био проширив; округли метод ствара контекст за методе за штампу и позива следећи начинCL-USER>(defmethodprint-object:around((pperson)stream)(print-unreadable-object(pstream:typet)(call-next-method)))#<STANDARD-METHODPRINT-OBJECT(:AROUND)(PERSONT)4020263743>; примарни метод исписује имеCL-USER>(defmethodprint-object((pperson)stream)(formatstream"~a"(slot-valuep'name)))#<STANDARD-METHODPRINT-OBJECTNIL(PERSONT)40202646BB>; нова класа id-mixin даје idCL-USER>(defclassid-mixin()((id:initarg:id)))#<STANDARD-CLASSID-MIXIN422034A7AB>; метод за штампање само исписује вредност id слотаCL-USER>(defmethodprint-object:after((objectid-mixin)stream)(formatstream" ID: ~a"(slot-valueobject'id)))#<STANDARD-METHODPRINT-OBJECT(:AFTER)(ID-MIXINT)4020278E33>; сада редефинишу класе особу да се укључи у mixin id-mixinCL-USER241>(defclassperson(id-mixin)((name:initarg:name)))#<STANDARD-CLASSPERSON4220333E23>; постоји инстанца * Лице-1 * сада има нови слот и ми га постављамо на 42CL-USER242>(setf(slot-value*person-1*'id)42)42; приказивање објеката поново. Функција штампања објеката сада има ефикасну методу, којом се позивају три методе: метод около, примарни метод и после методом.CL-USER243>*person-1*#<PERSONEvaLuatorID:42>
Примери динамичких програмских језика
Популарни динамички програмски језици укључују JavaScript, Python, Ruby, PHP, Lua и Perl. Следећи се генерално сматрају динамичке језике:
^Meijer, Erik; Peter Drayton (2005), Static Typing Where Possible, Dynamic Typing When Needed: The End of the Cold War Between Programming Languages, Microsoft Corporation, CiteSeerX10.1.1.69.5966
^See example of use on pp. 330 of Larry Wall's Programming Perl. Wall, Larry; Christiansen, Tom; Orwant, Jon (14. 7. 2000). Programming Perl. O'Reilly Media, Incorporated. ISBN978-0-596-00027-1.CS1 одржавање: Формат датума (веза)