Lisp (programski jezik)
Lisp (istorijski, LISP) je familija programskih jezika sa dugom istorijom. Lisp je drugi najstariji viši programski jezik koji se i danas veoma koristi. Jedino je Fortran stariji (godinu dana).[1][2] Danas postoji veliki broj dijalekata Lisp-a, a najpoznatiji među njima su Common Lisp i Scheme. Čisti Lisp je primer funkcionalnog programskog jezika. U funkcionalnom programiranju, funkcije se primenjuju na argumente i vrednosti. Vraćene vrednosti se koriste kao argumenti za druge funkcije. Funkcionalno programiranje je suprotno proceduralnom programiranju, gde se koriste naredbe koje menjaju okruženje programa na neki način, kao što je pripisivanje vrednosti promenljivim. U funkcionalnom programiranju, te promene okruženja se minimizuju korišćenjem vrednosti koje vraća pozvana funkcija kao direktan ulaz u drugu funkciju, bez upotrebe pripisivanja naredbi. Ime LISP je nastalo od "LISt Processor". Povezane liste su jedan od glavnih tipova podataka. IstorijatLisp je projektovao Džon Makarti 1958. godine. Lisp je prvi put implementiran od strane Stiva Rasela na IBM 704 računaru. Rasel je pročitao Makartijev rad i zaključio da izračunavanje u Lispu može da se implementira na mašinskom jeziku. Rezultat toga je interpretator koji je mogao da pokreće Lisp programe, ali i da računa vrednosti Lisp izraza. Prvi kompletan Lisp kompajler, napisan u Lisp-u, implementirali su Tim Hart i Majk Levin 1962. godine. Tokom 1980-ih i 1990-ih radilo se na ujedinjavanju novih dijalekata Lisp-a. Tako je nastao programski jezik Common Lisp. Prvi standard za Common Lisp, "ANSI X3.226-1994 Information Technology Programming Language Common Lisp.", objavio je ANSI 1994. godine. Edsger Dajkstra je na dodeli Tjuringove nagrade 1972. godine rekao: "Sa nekoliko osnovnih principa svog zasnivanja, on (LISP) je pokazao izuzetnu stabilnost. Osim toga, LISP je bio nosač značajnog broja najsavremenijih kompjuterskih aplikacija. LISP je u šali opisan kao "najinteligentniji način da se zloupotrebi računar". Mislim da je takav opis veliki kompliment, jer prenosi pun ukus slobode: on je pomogao veliki broj naših najtalentovanijih kolega u razmišljanju o ranije nemogućim stvarima."[3] Sintaksa i semantikaSimbolički izrazi (S-izrazi)Lisp je jezik koji se oslanja na izraze. Kada se izraz evaluira, on vraća vrednost, koja se može iskoristiti u drugim izrazima. Svaka vrednost može biti bilo koji tip podataka. U Lisp-u se navode dva tipa sintakse: S-izrazi (simbolički izrazi), koji oslikavaju unutrašnju reprezentaciju i koda i podataka, i M-izrazi (meta izrazi), koji izražavaju funkcije S-izraza. Skoro svi Lisp jezici danas koriste S-izraze za kod i podatke. Ono što je Lisp odmah odvojilo od drugih porodica jezika, jeste upotreba zagrada. Sintaksa koja koristi S-izraze je zaslužna za lakše korišćenje programskog jezika Lisp. Međutim, sintaksa Lisp-a nije ograničena na tradicionalnu notaciju pomoću zagrada. Može se proširiti i uključiti i druge notacije. Oslanjanje na izraze daje veliku fleksibilnost jeziku. Lisp funkcije su napisane kao liste, stoga se one mogu obrađivati kao bilo koji drugi podaci. Ovo omogućava lako pisanje programa koji koriste druge programe (metaprogramiranje). Mnogi Lisp dijalekti koriste ovu odliku, koristeći makro sisteme, što omogućava proširenje jezika gotovo bez ograničenja. ListeLista se zapisuje tako što se između zagrada navedu elementi liste, odvojeni razmacima. Na primer, Prazna lista Izrazi se zapisuju kao liste, koristeći prefiksnu notaciju. Na primer, ako navedemo (A B C D)
A predstavlja ime funkcije (ime makroa, lambda izraz ili ime specijalnog operatora), dok su B, C i D argumenti. Liste mogu biti ugnježdene. Na primer: (A (B C) D (E (F G)))
OperatoriAritmetički operatori se tretiraju na sledeći način: (+ 1 2 3 4)
Ovaj izraz ima vrednost 10. Ekvivalentan izraz u infiksnoj notaciji jeste "1 + 2 + 3 + 4". Aritmetički operatori u Lisp-u su n-arne funkcije, tako da mogu imati bilo koliko argumenata. Operator inkrementiranja u C-u "++" ovde je implementiran kao: (incf x)
što je ekvivalentno sa (setq x (+ x 1)), koje vraća novu vrednost od x. Specijalni operatori, koji se ponekad nazivaju i specijalnim formama obezbeđuju kontrolne strukture. Na primer, specijalni operator if ima tri argumenta. Ako prvi argument nije nil, određuje se vrednost drugog argumenta, a ako jeste, onda se određuje vrednost trećeg argumenta. Na primer, (if nil
(list 1 2 "foo")
(list 3 4 "bar"))
biće Lambda izrazi i definicija funkcije
(lambda (arg) (+ arg 1))
predstavlja funkciju koja uzima jedan argument, vezuje ga za ((lambda (arg) (+ arg 1)) 5)
vraća vrednost 6. AtomiU prvobitnom LISP-u su postojale dva osnovna tipa podataka: atomi i liste. Lista je konačan niz elemenata gde je svaki element za sebe lista ili atom, a atom je ili broj ili simbol, koji ima formu identifikatora. Na primer, (FOO (BAR 1) 2)
sadrži tri elementa: simbol FOO, listu (BAR 1) i broj 2. Suštinska razlika između atoma i listi jeste ta da su atomi nepromenljivi i jedinstveni, dok je svaka lista poseban objekat koja može da se menja nezavisno od drugih listi. Liste i elementi liste![]() Lisp lista je jednostruko povezana lista. Svaka ćelija liste se naziva Ako uzmemo da nam dati Veoma se često koriste kod rekurzivno napisanih funkcija koje u svom prvom prolazu obrađuju samo jedan element, a zatim se sa cdr uzima ostatak liste koji se rekurzivno prosleđuje istoj funkciji da isti posao obavi i za sve druge elemente Zbog toga što su
Funkcije za rad sa listamaLisp ima mnoge ugrađene funkcije za pristup i kontrolu listi. Lista se može kreirati direktno pomoću funkcije (list 1 2 'a 3)
;Output: (1 2 a 3)
(list 1 '(2 3) 4)
;Output: (1 (2 3) 4)
Funkcija (cons 1 '(2 3))
;Output: (1 2 3)
(cons '(1 2) '(3 4))
;Output: ((1 2) 3 4)
Funkcija (reverse '(a b c d))
;Output: (d c b a)
Funkcija (length ‘(a (b c) d))
;Output: 3
(length ‘(a b c d))
;Output: 4
Funkcija (append '(1 2) '(3 4))
;Output: (1 2 3 4)
(append '(1 2 3) '() '(a) '(5 6))
;Output: (1 2 3 a 5 6)
Postoji još mnogo funkcija ovog tipa, koje proveravaju da li je određen argument prazna lista, da li je taj argument uopšte lista i slične. ( null , listp…) Deljene struktureLisp liste, koje su jednostruko povezane, mogu da podele strukturu međusobno. To jest, dve liste mogu da imaju isti rep ili krajnji niz (setf foo (list 'a 'b 'c))
(setf bar (cons 'x (cdr foo)))
liste Međutim, ukoliko se, u nekom trenutku, zameni b ili c u Samoevaluirajući oblici i operator navođenja quoteLisp određuje vrednost izraza koji korisnik unese. Simboli i liste određuju vrednost nekog drugog izraza, uglavnom jednostavnijeg. Na primer, simbol određuje vrednost promenljive koju imenuje; Svaki izraz može biti obeležen kako bi se sprečila njegova evaluacija (ako je potreban za simbole i liste). To je uloga specijalnog operatora Samoevaluirajući oblici i forme navođenja su u Lisp-u ekvialentni sa literalima. To omogućava modifikaciju (promenljivih) literala u programskom kodu. Na primer, ako funcija vraća neku formu navođenja i kod koji poziva funkciju modifikuje formu, to može promeniti ponašanje funkcije u narednim iteracijama. (defun should-be-constant ()
'(one two three))
(let ((stuff (should-be-constant)))
(setf (third stuff) 'bizarre)) ; loše!
(should-be-constant) ; vraća (one two bizarre)
Prostor imenaLisp je podeljen oko upotrebe dinamičke i statičke (odnosno leksičke) upotrebe prostora imena. Clojure, Common Lisp i Scheme podrazumevano koriste statičko definisanje polja promenljive, dok Newlisp, Picolisp i ugrađeni jezici u Emacs-u i AutoCAD-u koriste dinamičko. Spisak struktura programskog koda; makroi i kompajleriOsnovna razlika između Lisp-a i ostalih jezika je u tome što je tekstualna reprezentacija programa prilično čitljiv opis same unutrašnje strukture podataka (povezanih listi, simbola, brojeva, karaktera, itd.) kao što je u osnovi Lisp sistema. Zahvaljujući tome, Lisp implementira veoma jak sistem makroa. Kao i u ostalim makro jezicima kao što je C, makro vraća kod koji može biti kompajliran. Za razliku od C-ovih makroa, u Lisp-u su makroi funkcije i u njima je moć Lisp-a. Pošto kod u Lisp-u ima istu strukturu kao liste, makroi mogu biti izraženi pomoću bilo koje funkcije za rad sa listama. Ukratko, sve što može Lisp sa strukturom podataka, Lisp makroi mogu sa kodom. U jednostavnoj implementaciji Lisp-a, ova struktura u vidu liste je direktno interpretirana da pokrene program; funkcija je doslovno deo strukture liste koja prevedena od strane interpretatora pri izvršavanju. Većina Lisp sistema sadrži i kompajler. On prevodi strukturu liste na mašinski jezik ili bajtkod za izvršavanje. Ovaj kod može biti pokrenut jednako brzo kao i u C-u, na primer. Makroi nude interesantne opcije.
Neke implementacije Lisp-a imaju mehanizam Evaluacija i read–eval–print petljaLisp jezici su najčešće korišćeni sa interaktivnom komandnom linijom, koja se može kombinovati sa IDE-om. Lisp čita unete izraze, evaluira ih i štampa rezultat. Zbog ovoga, Lisp komandna linija se naziva "read–eval–print petlja", odnosno REPL.
Na primer, ako se ukuca tekst Treba napomenuti da se
Simbol Posao funkcije Za implementaciju Lisp REPL-a, neophodno je implementirati navedene tri funkcije i funkciju "beskonačna petlja". Naravno da implementacija funkcije Kada je ovo završeno, REPL nije ništa drugo do jedna linija koda: (loop (print (eval (read)))). Lisp REPL omogućava redigovanje ulaza, istoriju ulaza, upravljanje greškama kao i interfejs dibagera. Lisp se uglavnom evaluira pohlepno. Kontrolne struktureLisp je prvobitno imao samo nekoliko struktura, ali veliki broj je dodavan tokom evolucije jezika. (Lisp-ov prvobitni uslovni operator, cond, prethodnik je kasnije if-then-else strukture. Pojedine Lisp-ove kontrolne strukture su specijalni operatori, ekvivalenti sintaksnim ključnim rečima drugih jezika. Izrazi koji koriste ove operatore imaju isti izgled kao pozivi funkcija, razlika je jedino u tome što argumenti ne moraju biti evaluirani ili u iterativnom slučaju mogu biti evaluirani više od jedanput. Za razliku od ostalih viših programskih jezika, Lisp dopušta programeru da implementira kontrolne strukture koristeći jezik. Nekoliko kontrolnih strukutura je implementirano kao Lisp makroi, a nekoliko njih mogu biti makro razvijeni od strane programera koji znaju kako to radi. I Common Lisp i Scheme imaju operatore za nelokalnu kontrolu toka. Razlike u ovim operatorima ujedno čine i razlike između ova dva dijalekta. Neretko, isti algoritam u Lisp-u može biti iskazan i imperativnim i funkcionalnim stilom. Scheme preferira funkcionalni stil koristeći repnu rekurziju. Kako god, imperativni stil je još uvek moguć. Stil koji preferiraju Common Lisp programeri bliži je programerima koji koriste struktuirane jezike kao što je C, dok je onaj koji preferiraju Scheme programeri bliži čisto funkcionalnim jezicima kao što je Haskell. Lisp ima široki spektar funkcija višeg reda koje su u relaciji sa itaracijom u naredbama. U mnogim slučajevima gde bi u drugom jeziku bila neophodna petlja (kao for u C-u) u Lisp-u stvar rešava funkcija višeg reda. PrimeriEvo primera Common Lisp koda. Osnovni "Hello World" program: (print "Hello world")
Lisp sintaksa je podesna za rekurziju. Matematički problemi kao što je nabrajanje rekurzivno definisanim skupovima jednostavno se izražavaju u ovoj notaciji. Računanje faktorijela: (defun factorial (n)
(if (= n 0) 1
(* n (factorial (- n 1)))))
Alternativna implementacija, često brža od prethodne ako Lisp sistem ima optimizaciju u vidu repne rekurzije: (defun factorial (n &optional (acc 1))
(if (= n 0) acc
(factorial (- n 1) (* acc n))))
Iterativna verzija u Common Lisp-u: (defun factorial (n)
(loop for i from 1 to n
for fac = 1 then (* fac i)
finally (return fac)))
Naredna funkcija obrće listu. (Ugrađena funkcija reverse radi istu stvar.) (defun -reverse (list)
(let ((return-value '()))
(dolist (e list) (push e return-value))
return-value))
Objektni sistemi
Spoljašnje vezeReference
|
Portal di Ensiklopedia Dunia