Läspa | |
---|---|
Semantik | multiparadigm : objektorienterad , funktionell , procedurprogrammering |
Språkklass | multiparadigm programmeringsspråk , funktionellt programmeringsspråk , procedurspråk , reflekterande programmeringsspråk [d] , metaprogrammeringsspråk [d] och tolkat programmeringsspråk |
Framträdde i | 1958 |
Författare | John McCarthy |
Utvecklaren | John McCarthy [1] och Steve Russell [d] |
Typ system | stark , dynamisk |
Dialekter |
Common Lisp ( CLOS ), Scheme , Arc , Clojure tilläggsspråk: AutoLisp och ELisp |
Blivit påverkad | Informationsbehandlingsspråk [d] |
påverkas | Io , Nemerle , Python , Ruby , Smalltalk , Logo , Factor , Perl , Nim |
Mediafiler på Wikimedia Commons |
Lisp ( LISP , från engelska LISt Processing language - "List processing language"; modern stavning: Lisp ) är en familj av programmeringsspråk , program och data i vilka representeras av system med linjära teckenlistor . Lisp skapades av John McCarthy för arbetet med artificiell intelligens och är fortfarande ett av de viktigaste verktygen inom detta område. Det används också som ett medel för konventionell industriell programmering, från inbäddade skript till massanvändning av webbapplikationer, även om det inte kan kallas populärt.
Det är ett av de äldsta (tillsammans med Fortran och Cobol ) högnivåprogrammeringsspråk som används idag [2] och det första språket som fortfarande används för att använda automatisk minneshantering och skräpinsamling [3] .
Traditionell Lisp har ett dynamiskt typsystem . Språket är funktionellt , men från tidiga versioner har det också drag av imperativitet , förutom att ha fullfjädrade symboliska bearbetningsmöjligheter , tillåter det att implementera objektorientering ; ett exempel på en sådan implementering är CLOS- plattformen .
Det är ett systemprogrammeringsspråk för de så kallade Lisp-maskinerna som tillverkades på 1980 -talet , till exempel av Symbolics .
Tillsammans med Ada- språket gick Lisp igenom en process av grundläggande standardisering för industriellt bruk, vilket resulterade i Common Lisp- dialekten , som senare standardiserades av ANSI . Dess implementeringar finns för de flesta plattformar.
Lisp är ett skiftlägesokänsligt språk. Språkets alfabet var ursprungligen begränsat till ASCII -teckentabellen , vissa moderna implementeringar stöder Unicode .
De grundläggande elementen i språket är symboler, atomer och dynamiska liststrukturer byggda av dem - S-uttryck .
En symbol i Lisp är ett objekt i maskinminnet, som är en samling "slots" - celler som lagrar referenser. Vissa platser har ett syfte som ursprungligen definierades av språket:
Uppsättningen av slots är dynamiskt expanderbar och kan därför användas som en lista över godtyckliga symbolegenskaper (du kan fritt utöka slotsystemet på ett sätt som är bekvämt för att lösa problemet). Denna representation tillåter oss att betrakta symboler som noder i ett nätverk med flera koordinater, där varje koordinat skrivs i sin egen lucka.
Atomer är symboler och tal. Siffror är inte Lisp-symboler, eftersom de bara kan ha sitt eget numeriska värde och inget annat. Samtidigt kan siffror, tillsammans med symboler, inkluderas i listor. Detta är anledningen till att kombinera dessa två begrepp i en allmän kategori.
Lisps grundläggande datastruktur är en dynamisk lista av atomer, definierad rekursivt som ett huvudobjekt och en svanslista kopplad till det. Eftersom huvudet på listan också kan vara en lista, är listan en form av representation av ett godtyckligt träd (översta listan i sig är roten, dess underlistor av den andra och efterföljande nivåerna är noder, atomer är blad). För atomer och listor använder språket en extremt primitiv parentessyntax: en symbol representeras av dess namn, ett tal representeras av dess värde och en lista representeras av en sekvens av listor och atomer omgivna inom parentes, med successiva atomer separerade med mellanslag vid behov.
En lista är en sekvens av element av vilket slag som helst, inklusive andra listor. Den (1 3/7 'foo #'+)består till exempel av ett heltal, ett rationellt bråktal, symbolen foo och en pekare till additionsfunktionen. Uttryck representeras av listor med prefix : det första elementet måste vara en form , det vill säga en funktion , operator , makro eller specialoperator ; andra element är argumenten för detta formulär , som skickas till formuläret för bearbetning. Aritmetiska operatorer skrivs enligt samma princip, till exempel (+ 4 (* 2 3))ger det 10 (i infixnotation är detta 2 * 3 + 4).
s_expression ::= atomic_symbol | "(" s_expression "." s_expression ")" | lista lista ::= "(" s_expression { s_expression } ")" atomic_symbol ::= bokstaven atom_part atom_part ::= tom | bokstaven atom_del | nummer atom_del bokstaven ::= "a" | "b" | "..." | "z" nummer ::= "1" | "2" | "..." | "9" tomt ::= " "En karaktäristisk egenskap hos ett Lisp-program är att absolut allt: både data och kod av vilken komplexitet som helst - beskrivs i denna primitiva syntax. Det finns två resultat av detta tillvägagångssätt:
Alla Lisp-program består av en sekvens av uttryck (former). Resultatet av programmet är att utvärdera dessa uttryck. Alla uttryck är skrivna som listor, en av Lisps huvudstrukturer, så de kan enkelt skapas inom själva språket. Detta gör att du kan skapa program som modifierar andra program eller makron , vilket gör att du kan utöka språkets kapacitet avsevärt.
Avancerade implementeringar av Lisp innehåller hundratals systemfunktioner, makron och operatorer. Här ges bara de av dem som ligger till grund för att arbeta med listor och skapa funktionsprogram i Lisp.
T och NIL Lisps inbyggda konstantsymboler, som betecknar logiskt sant respektive falskt. Värden Toch NILreturneras av logiska operatorer och jämförelseoperatorer och funktioner. Dessutom har symbolen NILytterligare en betydelse - den kan beteckna en tom lista. CAR och CDR Funktionerna returnerar huvudet och svansen på listan, respektive: (CAR '(A B C D)) ==>> A(nedan i exemplen ==>>betyder att som ett resultat av att utvärdera vänster sida, producerar Lisp-tolken det som finns till höger) (CAR '((A B)(C D))) ==>> (A B) (CDR '(A B C D)) ==>> (B C D) (CDR '((A B)(C D))) ==>> ((C D)) Observera att i det senare fallet returneras en lista i en lista: argumentets svans är en enelementslista, som i sig är en tvåelementslista. Formellt, i ren funktionell programmering, är innebörden av huvudet på en tom lista odefinierad, men Lisp (åtminstone i de flesta dialekter) har en konvention om att både huvudet och svansen på en tom lista är lika NIL. (CAR NIL) ==>> NIL (CDR NIL) ==>> NIL Systemfunktioner CARfick CDRså ovanliga namn av historiska skäl. IBM 704 -maskinen , på vilken McCarthy skapade den allra första implementeringen av Lisp, innehöll instruktioner för att ändra delar av ett maskinord. Maskinordet betraktades som en struktur med prefix-, dekrement-, tagg- och adressfält. Funktioner CAR(förkortning av Innehåll i adressdelen av registret ) och CDR( Innehållet i registrets nedskärningsdel ) fick sina namn i enlighet med dessa fält [5] . I denna implementering användes adress- och dekrementeringsfälten för att lagra pekare till listans huvud respektive baksida. I vissa nya implementeringar av Lisp har de traditionella namnen ersatts av FIRSToch REST(eng. "första" respektive "återstående") eller kompletterats med dessa synonymer. C*R Här, istället för asterisken "*" i funktionsnamnet, kan det finnas från 2 till 4 bokstäver "A" och "D" i valfri kombination. Det vill säga funktionerna CDDDDR, CADARoch CADDRså vidare är möjliga. Att anropa en sådan funktion motsvarar att kapsla en motsvarande uppsättning funktioner CARoch CDRtill exempel (CADAR '((A B C) D E F))matchar (CAR (CDR (CAR '((A B C) D E F))))och returnerar värdet "B". Behovet av sådana konstiga funktioner är relaterat till den ofta upprepade uppgiften: att extrahera ett visst element från listan, vars position är känd. NACKDELAR Tar ett huvud och en svans som argument och skapar en lista eller ett prickat par av dem om argumenten är atomer: (CONS 'A '(B C D)) ==>> (A B C D) — sammanfoga en atom till en lista; (CONS '(A B) '((C D))) ==>> ((A B) (C D)) - lägga till en lista till huvudet på en annan lista; (CONS 'A 'B) ==>> (A . B) - skapande av ett punktpar med två atomer. LISTA Denna funktion returnerar en lista över dess argument: (list 1 3/7 'foo) ==>> (1 3/7 'foo) Om det inte finns några argument returneras en tom lista: (list) ==>> NIL Om vissa element är uttryck, utvärderas deras värde först: (list 1 2 (list 1 2)) ==>> (1 2 (1 2)). CITAT Systemoperatören QUOTEundertrycker utvärderingen av sitt argument. Om den inte används försöker Lisp-tolken, efter att ha fått en lista eller symbol vid ingången, att beräkna den: för symbolen returneras dess värde, för listan - resultatet av att anropa funktionen vars namn finns i listans huvud, med parametrar - listans svans. Om det är nödvändigt att tolken inte beräknar värden, utan tar en symbol eller en lista "som den är", ansök till den QUOTE. (LIST 1 2 (QUOTE(LIST 1 2))) ==>> (1 2 (LIST 1 2)) (QUOTE (list 1 2 (list 1 2))) ==>> (LIST 1 2 (LIST 1 2)) Eftersom undertryckning är en mycket vanlig operation, finns det syntaktisk socker som förkortar det - istället för den fullständiga formen av QUOTE-anropet kan du helt enkelt sätta en apostrof framför uttrycket: (LIST 1 2 '(LIST 1 2)) ==>> (1 2 (LIST 1 2)). EVAL Denna funktion är faktiskt Lisp-tolken. Eftersom den är motsatsen till CITAT, utvärderar den värdet av dess argument. (EVAL '(LIST 1 2 '(LIST 1 2))) ==>> (1 2 (LIST 1 2)) (EVAL '(LIST 1 2 (EVAL'(LIST 1 2)))) ==>> (1 2 (1 2)) Möjligheten att direkt och direkt anropa tolken, tillsammans med identiteten för programmets struktur och data, gör att du kan generera och direkt köra alla Lisp-program i systemet utan några begränsningar. KOND Generaliserad villkorlig konstruktion. Ser ut som: (COND ((Условие1)(Выражение1)) ((Условие2)(Выражение2)) …) Villkor1, Villkor2 och så vidare utvärderas sekventiellt tills nästa VillkorN visar sig vara sann (börjar ha värdet T). Då kommer motsvarande ExpressionN att exekveras och dess värde kommer att returneras som anropsvärdet COND. Om det sanna villkoret inte hittas CONDreturneras värdet NIL. Det är vanligt att sätta det sista villkoret till COND, Toch därigenom säkerställa att om alla andra villkor misslyckas, kommer det sista av uttrycken att utvärderas; så här skapas en analog av grenen av ELSEvillkorliga operatörer av imperativa programmeringsspråk. DEFUN En konstruktion som låter dig definiera en funktion. Det allmänna (förenklade) definitionsformatet är som följer: (DEFUN Имя (Параметр1 Параметр2 …) Выражение1 Выражение2 …) Här Namn är namnet på funktionen. Motsvarande symbol, om den inte redan finns, skapas i systemet och funktionsdefinitionen kommer att skrivas till dess funktionsplats. I framtiden tolkar Lisp-tolken, efter att ha träffat namnet i huvudet på den beräknade listan, det som ett anrop till denna funktion med parametrarna listade i svansen. Parameter1 och så vidare är namnen på funktionens formella parametrar. Sekvensen Expression1, Expression2 och så vidare är en sekvens av beräkningsbara uttryck som kan använda parametrar och globala systemvariabler. När en funktion kallas Uttryck utvärderas sekventiellt och värdet på funktionen kommer att returneras som det värde som utvärderats av det sista uttrycket i ordningen.Specialoperatorer låter dig styra sekvensen av beräkningar. Grenar och slingor implementeras med deras hjälp . Operatorn låter dig utvärdera ett av två uttryck beroende på uppfyllandet av ett villkor, vilket också är ett uttryck. Om resultatet inte är FALSK (inte ), utvärderas det första argumentet, annars det andra. Till exempel returnerar den alltid . ifnil(if nil (list 1 2 "foo") (list 3 4 "bar"))(3 4 "bar")
Lisp kräver inte, generellt sett, att explicit specificera typerna av variabler, parametrar och funktioner. Men det betyder inte att det inte finns några typer i Lisp. Lisp använder dynamisk typning , när datatypen inte refererar till en variabel (parameter, funktion), utan till ett värde . Detta innebär att en variabel kan, i avsaknad av särskilda specifikationer, innehålla ett värde av vilken datatyp som helst och vid olika tidpunkter ha värden av olika typer. Värdetyper bestäms av hur dessa värden skapas. Till exempel, i ett uttryck (CONS 10 (CONS 2.01 (CONS 'A (CONS "abc" NIL))))i samma (första) parameter, får samma funktion ( CONS) sekventiellt ett heltal , ett flyttal , en atom och en sträng.
Avancerade moderna Lisp-system, inklusive standarden Common Lisp, har en stor uppsättning inbyggda datatyper organiserade i ett hierarkiskt system där en typ kan ha flera supertyper och flera undertyper. Roten till hierarkin är den inbyggda typen T, supertypen av alla typer, den sista typen av hierarkin är typen NIL, undertypen av alla typer.
Illustrationen till höger visar ett fragment av denna hierarki: supertypen för värden av numeriska typer är NUMBER, dess undertyper - RATIONAL, FLOAToch COMPLEX, - representerar respektive ett rationellt tal , ett flyttaltal och ett komplext tal , den första av som i sin tur har undertyper INTEGER( heltal ) och RATIO( rationell bråkdel ), den andra - flera undertyper som representerar flyttal med varierande grad av precision, och så vidare.
Typer skapade av programmeraren är också inbyggda i detta system.
Eftersom inte alla värdetyper är giltiga för alla operationer, resulterar tillämpning av operationer på vissa värden i körtidsfel. Programmeraren kan antingen ignorera denna funktion (vilket kommer att få programmet att krascha om data av oavsiktlig typ påträffas), eller använda undantagshantering, eller kontrollera om värdet som han ska arbeta med (till exempel skickat till funktionen som en parameter) tillhör den önskade typen, och i händelse av en missmatchning, välj ett annat sätt att lösa problemet eller konvertera data till önskad typ, när det är möjligt. För att arbeta med typer finns det: ett typkontrollpredikat TYPEP, en typbestämningsfunktion TYPE-OFoch för typkonvertering, om den kan utföras, en hel uppsättning högspecialiserade funktioner och en allmän funktion COERCE. Typkontroll underlättas av att Lisps typsystem, som nämnts ovan, är hierarkiskt. Vilken som helst av undertyperna är kompatibel med vilken som helst av dess supertyper. Till exempel definieras aritmetiska operationer för vilken kombination av alla typer av tal som helst, så för tillåtligheten att använda till exempel addition räcker det att kontrollera med predikatet TYPEPatt operanderna är av typen NUMBER.
( defun SmartPlus ( a b ) ( cond (( och ( skriv a 'number ) ( typp b 'number )) ( + a b )) ( t noll )))Så i exemplet ovan returnerar SmartPlus-funktionen summan av dess argument om de är tal av någon typ, eller noll om minst ett av dem inte är ett tal. I det här fallet kommer den specifika returtypen att bero på de faktiska typerna av parametrar:
( SmartPlus 1 2 ) ==> 3 ( typ av ( SmartPlus 1 2 )) ==> ( HELTAL 0 4611686018427387903 ) ( SmartPlus 1 1.2 ) ==> 2.2 ( typ av ( SmartPlus 1 2 ) ==> S 1 . -FLYTTA ( SmartPlus 2 2/3 ) ==> 8/3 ( typ av ( SmartPlus 2 2/3 )) ==> FÖRHÅLLNING ( SmartPlus "abc" 20 ) ==> NIL ( typ av ( SmartPlus "abc) " 20 )) ==> NULLAtt använda dynamisk typning är inte alltid bekvämt, särskilt när man använder en kompilator. För det första, frånvaron av restriktioner för vilka typer som värdena för en variabel eller parameter kan tillhöra minskar kompileringens effektivitet. För det andra tillåter det inte statiskt (under kompilering, inte programkörning) att upptäcka fel relaterade till brott mot typkonsistens. I situationer där dessa olägenheter är betydande tillåter Lisp att använda en speciell operatör för att DECLAREspecificera typerna av parametrar och variabler, specificera dem med nödvändig precision (du kan specificera både konkreta typer, till exempel, RATIOeller SHORT-FLOAT, och supertyper av vilken grad av generalitet som helst, till exempel, NUMBER).
Lisp designades ursprungligen som ett funktionellt programmeringsspråk med vissa imperativa funktioner införda av skäl för enkel praktisk användning. Men den valda formalismen och den uppsättning primitiver som språket bygger på gjorde det möjligt att utvidga det i olika riktningar. Under decennier av drift och utveckling av språket har det absorberat nästan alla befintliga programmeringsmetoder och kan för tillfället anses vara ett av de mest kraftfulla multiparadigmspråken på hög nivå.
Det funktionella paradigmet är "inhemskt" hos Lisp, eftersom grunden för dess arkitektur är kyrkans lambdakalkyl . Egentligen var det med Lisp som funktionell programmering började som en praktisk metod för mjukvaruutveckling. Lambda-uttryck är fullfjädrade språkobjekt i Lisp, som inte bara tillåter direktanrop, utan även tilldelning, lagring som symbolvärde, passerar som en anropsparameter och återkommer som ett resultat. Således stöder Lisp funktionaliteter, det vill säga funktioner som tar som parametrar och returnerar andra funktioner som ett resultat.
I olika Lisp-dialekter är förhållningssättet till karaktären av funktioner som språkobjekt något olika. I Common Lisp är funktioner och lambda-uttryck en separat kategori av programobjekt för vilka det finns specifika regler och begränsningar; i synnerhet betyder detta att en symbol har separata luckor för värdet och för den funktion som är associerad med den symbolen, och i detta avseende är en funktion inte exakt samma som ett dataelement. I andra dialekter, som T-Lisp eller Scheme, är funktioner så kallade " fulla medborgare " - de kan fritt tilldelas variabler, skickas som anropsparametrar och returneras som anropsresultat.
Den nuvarande Lisp-standarden, Common Lisp, har kritiserats av anhängare av "ren" funktionell programmering eftersom inte all dess funktionalitet är teoretiskt "ren". Detta är sant, eftersom Common Lisp utformades som ett universellt industrispråk, och i ett antal fall gavs överväganden om praktisk ändamålsenlighet medvetet företräde framför hänsyn till teoretisk renhet. Ändå var och förblir Lisp ett funktionellt programmeringsspråk.
Till en början har Lisp-syntaxen förmågan att beskriva algoritmer genom att lista sekvensen av nödvändiga åtgärder. Det ligger i det så kallade "implicita PROGN" som stöds i strukturen av Lisps lambda-anrop: på den plats där kommandot som ligger till grund för lambda-uttrycket ska placeras kan inte ett utan flera kommandon skrivas, och resultatet av lambdasamtalet blir resultatet det sista av dem. Således stöder Lisp implicit sekventiell exekvering av operationer. Förutom implicit PROGN stöds explicita imperativa mekanismer för imperativ programmering:
Common Lisp har en speciell plats i LOOP-systemmakrot. Det låter dig skapa ett fragment i ett Lisp-program skrivet i ett programmeringsspråk med den vanliga imperativstrukturen och infixnotationen för operatorer.
Den enklaste makroprogrammeringsmöjligheten som finns tillgänglig i alla implementeringar av Lisp är möjligheten att anropa en tolk ( EVAL- funktionen ) direkt och skicka vilken liststruktur som helst till den som ett program. Detta tillåter toppnivåprogrammet att fungera som en makrogenerator, det vill säga att generera körbar kod som kommer att exekveras. Till exempel:
( defun name ( name lv ) ( eval ( cons 'defun ( cons name ( cdr lv ))))) ( namn 'add ' ( lambda ( x y ) ( + x y )))) ( lägg till 5 7 ) ==>12Här назватьkonstruerar funktionen en ny funktionsdefinition från namnet som skickats till den och ett lambda-uttryck, och exekverar sedan denna definition med eval. Som ett resultat av detta dyker en ny funktion (i detta exempel funktion сложить) upp i systemet och kan anropas på vanligt sätt.
Denna funktion används dock sällan på grund av dess krånglighet. Makrosystemet är mycket vanligare . Moderna varianter av Lisp, inklusive Common Lisp-standarden, har avancerade funktioner för att skapa och använda makron . En makrodeklaration i Lisp är syntaktisk lik en funktionsdeklaration (den enda skillnaden är användningen av nyckelordet defmacro istället för defun i deklarationen), men makrots beteende är väsentligt annorlunda: varje anrop till makrot "expanderas" vid den tidpunkt då programmet översätts, genererar kod som, vid körning, exekveras enligt följande: som om den skrevs direkt på anropsplatsen. En annan skillnad mellan makron och vanliga funktioner är att deras argument inte utvärderas som standard. Implementeringen av exemplet ovan som ett makro kan se ut så här:
( defmacro name ( name lv ) ( cons 'defun ( cons name ( cdr lv )))) ( namn add ( lambda ( x y ) ( + x y ))) ( lägg till 12 8 ) ==>20Det finns två synliga skillnader: det finns inget anrop i makrodefinitionen evaloch apostrof innan parametrarna inte används i dess anrop, eftersom makroparametrar inte utvärderas. Men en annan skillnad är mycket viktigare: om i det första exemplet konstruktionen av en ny funktion sker under körningen av programmet, så utförs expansionen av makrot under översättningen av programmet, så att kompilatorn får möjlighet att bearbeta funktionen сложить. Syntaxfel i bildandet av funktioner i makron upptäcks också inte under körningen av programmet, utan även i översättningsstadiet.
Dessutom stödjer ett antal Lisp-implementeringar skapandet av så kallade "läsmakron" - makron som direkt transformerar programmets text. Makron låter dig definiera nya språkkonstruktioner på ett transparent sätt och till och med utöka syntaxen för språket. Den senare möjligheten används aktivt när man implementerar i Lisp metoder och programmeringsverktyg som initialt inte stöds i den.
Lisp var inte utformat som ett objektorienterat språk. Själva det objektorienterade programmeringsparadigmet utvecklades ett och ett halvt decennium senare än Lisp, men när det dök upp och blev populärt lades objektfunktioner till detta språk.
Lisps kärnfunktioner gör det inte bara möjligt utan enkelt att lägga till ett objektorienterat delsystem till Lisp. På grund av förekomsten av egenskaper (slots) för symboler, stöder Lisp naturligt inkapsling . De funktionella egenskaperna hos Lisp (stöd för funktionaliteter, tilldelning av funktioner till variabler och lagring av dem i symbolegenskaper) gör det möjligt att associera kod (metoder) med data (objekt). Slutligen säkerställer språkets dynamiska natur, i kombination med ovanstående funktioner, det polymorfa beteendet hos kod och data i ett program. Den enda komponenten i ett OOP-system som inte finns i base Lisp är arv, men det kan implementeras utan svårighet. Således innehåller Lisp alla element som OOP-tekniken är baserad på, och implementeringen av dess stöd i språket kommer ner till skapandet av motsvarande syntaktiska element. Tack vare den utvecklade makromekanismen kan de läggas till med hjälp av själva språket, utan att behöva utöka den grundläggande syntaxen och modifiera kompilatorer. Ett enkelt och elegant exempel på att skapa ditt eget OOP-undersystem i Lisp finns i Paul Grahams ANSI Common Lisp [6] .
Bland de kommersiellt kända objektorienterade tilläggen av Lisp bör Flavours-objektsubsystemet, som ingick i Zetalysp-systemet, nämnas först och främst. Detta delsystem gav klassdeklarationer (smaker), enkel och multipel arv, polymorfa klassmetoder, ett Smaltalk-liknande objektinteraktionssystem genom meddelandeöverföring (implementerat som ett objektmetodanrop). Ett annat exempel är LOOPS (Lisp Object-Oriented Programming System), ett objektundersystem implementerat 1983 på Interlisp-dialekten.
Objektsystemet CLOS (Common Lisp Object System), som ursprungligen skapades utöver Common Lisp, och som senare ingick i språkstandarden, liknar Flavors och stöder i princip samma uppsättning funktioner som är standard för nästan alla moderna objektorienterade språk . Användningen av objektorienterad programmering i Lisp är främst förknippad med att lösa modellerings- och/eller kontrollproblem, som till sin natur framgångsrikt kombineras med objektorienterad teknologi. Till exempel var en av de första tillämpningarna av Flavours-systemet att interagera med ett användargränssnitt med flera fönster, som är helt rätt att modellera som en uppsättning meddelandeobjekt.
Författaren till Lisp är John McCarthy , som vid tiden för skapandet av språket arbetade vid Massachusetts Institute of Technology (MIT) som professor i kommunikation. Tillsammans med Marvin Minsky var han engagerad i arbete med artificiell intelligens, i samband med vilket det fanns ett behov av att skapa ett programmeringsspråk lämpligt för de uppgifter som löses inom detta område. Arbetet med språkskapande utfördes av McCarthy vid MIT mellan 1958 och 1963 , varefter han flyttade till Stanford University i Kalifornien, där han fick positionen som "professor i artificiell intelligens".
Lisp baserades på det tidiga IPL -språket utvecklat av Newell, Shaw och Simon. IPL var ett listbearbetningsspråk och var avsett att implementera Logic Theorist-projektet, ett artificiellt intelligenssystem utformat för att automatiskt härleda matematisk logiks satser. IPL var ett ganska lågnivåspråk, men det implementerade redan sådana grundläggande idéer som en enda mekanism för att lagra program och data i form av listor - hierarkiska strukturer av element länkade av länkar (själva idén om en listrepresentation av kunskap lånades från forskning inom psykologi och associativt minne), såväl som idén om dynamisk minnesallokering. Efter att ha bekantat sig med IPL 1956 fick McCarthy idén att implementera IPL-listbearbetning i Fortran , som designades på IBM vid den tiden (och under samma IBM 704 -system som McCarthy arbetade med på MIT), men denna idé har inte genomförts. McCarthy deltog senare i arbetet med "språkkommittén på hög nivå" som utvecklade Algol , men även där mottogs hans förslag kallt. Som ett resultat kom McCarthy på idén att skapa ett nytt programmeringsspråk.
Till en början formulerade McCarthy en listformalism för att beskriva data ( S-uttryck ) och en mekanism för att beskriva lambda-uttryck utifrån den , vilket gjorde det möjligt att skriva program som uppsättningar av funktioner presenterade i listform. Som McCarthy skrev senare, planerade han ursprungligen att använda en separat formalism för att skriva program, annorlunda än S-uttryck, men detta visade sig vara överflödigt. När McCarthy med sin listnotation beskrev hur tolken av ett nytt språk skulle fungera (en formalism som skulle bli känd som "Lisp on Lisp"), märkte Steve Russell att nu, för att skapa en verklig fungerande tolk, räcker det bara för att översätta denna notation till maskinkod. McCarthy var skeptisk till denna idé, men Russell gjorde faktiskt detta arbete och fick den första Lisp-tolken för IBM 704-datorn. Senare användes idén om att skriva en språköversättare på Lisp själv upprepade gånger, och inte bara i funktionella och logiska språk, men också i imperativa.
Historiskt sett var den första implementeringen av Lisp som inkluderade alla moderna grundläggande delar av språket en tolk som kördes på IBM 704, som dök upp i oktober 1958. Detta låter oss förresten tala om Lisp som ett av de två äldsta högnivåspråken som har varit i bruk från skapelseögonblicket till nutid (det första är Fortran). Dessutom behöll Lisp sin ledning i ytterligare ett avseende. Faktum är att aktivt arbete med dynamiska listor gjorde det omöjligt att manuellt hantera minnet, vilket delvis är bevarat på imperativa språk till denna dag. Skapandet av nya listceller och listor och utgången från användningen av befintliga Lisp-program är så aktiva att det är nästan omöjligt att göra utan ett automatiskt minneshanteringssystem som skulle kontrollera användningen av objekt som tidigare skapats i minnet och med jämna mellanrum radera de av dem som har upphört att användas, det vill säga sophämtningssystem . McCarthy var tvungen att implementera detta system, vilket gör Lisp bland annat också till det äldsta programmeringsspråket som används idag med automatisk minneshantering och sophämtning.
Senare skapades implementeringar för IBM 7090, och senare för IBM 360- och 370-serien. IBM-datorer visade sig vara obekväma för att arbeta i interaktivt läge, vilket ledde till att en liten grupp utvecklare i slutet av 1950-talet, inklusive de som tidigare arbetat på IBM, separerade i det oberoende företaget Digital Equipment Corporation (DEC). Dess första produkt var PDP-1- datorn , ursprungligen fokuserad på interaktivt driftläge. På denna maskin, 1960, implementerades det interaktiva systemet Lisp 1, som inkluderar en integrerad tolk, källkodsredigerare och debugger, som gjorde det möjligt att utföra hela arbetscykeln på programmet direkt i systemet. I själva verket var det den första "programmeringsmiljön" i den mening som införs i detta koncept nu. Samtidigt publicerades McCarthys artikel "Recursive Functions of Symbolic Expressions and their Computation by Machine." i tidningen Communications of ACM, där Lisp beskrevs som en algebraisk formalism på Lisp själv. Artikeln blev en klassiker, och "Lisp on Lisp"-formalismen har sedan dess blivit en av de mest använda i litteraturen om programmeringsteori. En annan teknisk innovation som dök upp i samband med implementeringen av "Lisp 1"-systemet var mekanismen som uppfanns av McCarthy, som gjorde att Lisp-tolken kunde köras samtidigt med utförandet av normalt beräkningsarbete i batch-läge (det som nu är känt som " tidsdelningssystem").
År 1962 var nästa version av det ursprungliga Lisp-systemet "Lisp 1.5" klar, där bristerna i den första versionen som upptäcktes under operationen eliminerades. Hennes beskrivning publicerades av MIT Press som en separat bok [7] . Eftersom manualen innehöll en beskrivning av implementeringen av systemet blev den grunden för skapandet av Lisp-system för många andra datorer både i USA och utomlands.
Trots användningen, ibland ganska aktiv, av Lisp i europeiska och asiatiska länder och skapandet av sina egna Lisp-system där, kommer de flesta av de vanliga dialekterna av Lisp från USA.
Mac LispMed början i början av 1960-talet lanserades MAC-projektet vid MIT, under vilket MacLisp utvecklades baserat på Lisp 1.5, främst inriktat på PDP-datorer. MacLisp var extremt kraftfull för sin tid, med hög beräkningseffektivitet och ett brett utbud av matematiska datatyper, inklusive vektorer, matriser och bitfält. Som en del av bidraget till utvecklingen av själva språket kan man notera läsmakron och lästabellerna som dök upp i MacLisp, som gjorde det möjligt att "avsluta" språket, utöka det i rätt riktning med nya strukturer. Undantagshantering och parallellbehandlingsmöjligheter ingick också i språket. MacLisp blev också det första Lisp-systemet för vilket en mycket effektiv kompilator implementerades .
Datoralgebrasystemet Macsyma skrevs helt i MacLisp , vars utveckling startades som en del av MAC-projektet 1968. Macsyma förblev det mest avancerade systemet i sitt slag under många år, med flera dialekter av Lisp skapade specifikt för att porta Macsyma till andra plattformar. En annan mycket berömd och fortfarande i bruk mjukvara som ursprungligen utvecklades i MacLisp är helskärmstextredigeraren Emacs .
MacLisp-systemet utnyttjades och utvecklades fram till 1980-talet, vilket hade en betydande inverkan på implementeringarna av Lisp som dök upp på 1960-1980-talet, inklusive att bli en av källorna för utformningen av Common Lisp-standarden. Driften av systemet upphörde praktiskt taget på 1980-talet, tillsammans med upphörandet av användningen av PDP-10/20-datorerna som det ursprungligen var baserat på. Systemen som utvecklats på MacLisp och de redan nämnda Macsyma och Emacs har överlevt en hel del .
InterlispMånga företag och forskningscentra i USA var involverade i utvecklingen av Lisp-system i mitten av 1960-talet. Interlisp var resultatet av de kombinerade ansträngningarna från BBN (Bolt, Beranek och Newman Inc.), SDS (Scientific Data Systems) och Xerox. BBN Research Center 1966 började skapa sin implementering av Lisp, fokuserad på PDP-10 och SDS-930-datorerna. PDP-versionen av BBN-Lisp använde en maskinvarusökning och kontextväxlingsmekanism speciellt utformad för att ge högeffektiv tidsdelning. BBN-Lisp blev populärt bland AI-forskare och bidrog i hög grad till att PDP-10/20-maskinerna förblev huvudverktygen i AI-arbetet fram till 1980-talet. I början av 1970-talet köpte Xerox Corporation det konkursmässiga SDS och ingick ett samarbete med BBN. Även om SDS-maskinerna inte var särskilt framgångsrika kommersiellt, var BBN:s implementering av Lisp tillräckligt lovande för Xerox att stödja dess vidareutveckling, vilket resulterade i att BBN-Lisp blev Interlisp .
Och 1974 började Xerox utveckla Alto personliga arbetsstation, ursprungligen orienterad mot Lisp. I detta system gjordes för första gången utveckling av utrustning och ett system med maskininstruktioner för ett specifikt programmeringsspråk. På basis av Interlisp skapades en förenklad version av Interlisp-D-systemet, designad för 1100-seriens Lisp-maskiner ("ättlingarna" till Alto-stationen). Dessa maskiner var de första som implementerade ett grafiskt användargränssnitt med flera fönster, använde högupplöst grafik och använde musen.
Systemet var omfattande dokumenterat och inkluderade en väldesignad IDE med en källkodsredigerare, debugger, tolk och många utvecklarhjälpmedel, vilket blev en av de exemplariska programmeringsmiljöerna för tidsdelningssystem. Mer än 500 funktioner implementerades i systembiblioteken, systemet hade ett stort antal inställningar som gjorde att det kunde ”skräddarsys” efter användaren. Implementeringar av Interlisp kördes så småningom på de mest använda tidsdelningsdatorerna.
När det gäller själva språket kan noteras att dialekten med alla dess karaktäristiska drag fixerades redan i mitten av 1970-talet, varefter inga grundläggande förändringar gjordes i språket. Detta fick systemet att släpa efter nyare utvecklingar vad gäller funktionalitet och att fixa några föråldrade designbeslut. Som ett resultat, i början av 1980-talet, upplevde Interlisp svårigheter både med kompatibilitet med nya system och med ytterligare expansion. De mest betydande bristerna är avsaknaden av en hierarki av datatyper, objekt och stängningar (likväl, 1983, implementerades LOOPS-objektsystemet, vilket gav möjlighet till objektorienterad programmering). Ännu viktigare är att Interlisp är baserat på dynamisk länkning, medan alla nya versioner av Lisp är statiska.
PSLLisp kom till Kalifornien med McCarthy, som flyttade till Stanford 1963. Under de närmaste åren utvecklades Lisp 1.6 (en direkt ättling till den "klassiska" Lisp 1.5), UCI Lisp (University of California, Irvine) och Stanford Lisp/360-systemen. Därifrån gick Lisp tillsammans med Anthony Hearn till University of Utah , där hon forskade inom området symbolisk matematik i tillämpningar av teoretisk fysik. Hearn föreslog att lösa dessa problem med Lisp, vilket resulterade i skapandet av datoralgebrasystemet Reduce 1968 .
Hearn publicerade Standard Lisp-specifikationen 1966, som han föreslog som grund för standardisering av språket. Hans förslag fick inget stöd, eftersom det inte godkändes av artificiell intelligensforskare, som påpekade ett antal särdrag i den föreslagna standarden som var oönskade för dem, i synnerhet överdriven bindning till typer. Baserat på denna specifikation implementerades dock Portable Standard Lisp, PSL, i Utah. Denna implementering användes för att utveckla Reduce och porta den till olika hårdvaruplattformar. Specifikt för att förbättra portabiliteten har en reducerad uppsättning systemfunktioner och strukturer inkluderats i PSL. Implementeringen baserades på ett mellanliggande lågnivå Lisp-liknande språk, SYSLisp; PSL-kärnan skrevs i SYSLisp, och resten av systemet skrevs i PSL själv. För PDP-10 implementerades SYSLisp-översättaren och en korskompilator skriven i samma SYSLisp, med hjälp av vilken PSL-kärnan kunde överföras till vilken annan hårdvara som helst. Med denna teknik har PSL och Reduce implementerats på en rad plattformar, inklusive DEC-10/20, VAX/UNIX, HP9000, Apollo, Wicat, IBM, Cray.
Således blev PSL ett av de första exemplen på implementeringen av "spin-up"-tekniken vid portering av mjukvarusystem till en ny arkitektur, när kärnan initialt skrivs på ett maskinoberoende mellanspråk för att portera systemet. , för vilka i sin tur implementeringar skapas på alla målplattformar. Ytterligare stöd för PSL utfördes av forskningscentret Hewlett-Packard i Kalifornien.
Franz LispMotivationen för Franz Lisp i slutet av 1970-talet var att skaffa ett Lisp-system för de nya VAX-datorerna för att köra Macsyma-systemet och annan Lisp-skriven programvara. Eftersom huvudmålet var att porta Macsyma, togs MACLisp som grund, men vissa föråldrade funktioner uteslöts från språket och nya mekanismer lades till, lånade från Zetalisp som utvecklades vid den tiden vid samma MIT. De viktigaste bidragen till skapandet av denna dialekt gjordes av University of Berkeley , University of Pennsylvania , Bell Labs , Livermore National Laboratory och Carnegie Mellon University . En av de främsta inspirationerna för projektet var professor vid Berkeley University, Richard Feitman, tidigare vid MIT och involverad i utvecklingen av det ursprungliga Macsyma-systemet. Bland skaparna av Franz Lisp fanns flera av hans elever. Namnet på systemet valdes för att hedra den berömda ungerske kompositören Franz Liszt (engelsk stavning: Franz Liszt).
Systemet implementerades 1981 i C för VAX 780/11 som kör UNIX . Kompilatorn som ingick i systemet fick namnet "Liszt" - efternamnet på kompositören som gav namnet till dialekten. 1982 portades systemet till Motorola 68000-processorn , sedan till ett antal 32-bitars personliga plattformar, som ett resultat av det blev den mest använda versionen av Lisp för både 32-bitars tidsdelningssystem och 32-bitars minidatorer och personliga arbetsstationer.
Franz Lisp distribuerades gratis under BSD-licensen, men Berkeley-studenten Friedrich Kunze kom på idén att skapa ett kommersiellt företag som skulle tillhandahålla högkvalitativt betald användarsupport och uppfylla beställningar för Franz Lisp-portering till ny hårdvara och mjukvaruplattformar. Det var en tid av aktiv tillväxt på datormarknaden och utsikterna såg goda ut. Företaget registrerades 1984 och fick namnet Franz Inc. Starten av företagets verksamhet var ganska framgångsrik, hon lyckades få ett kontrakt för att porta Franz Lisp till Sun-plattformen, och senare - flera liknande erbjudanden. Men 1985, under påtryckningar från det amerikanska försvarsdepartementet, började den amerikanska Lisp-gemenskapen en aktiv omorientering mot en ny dialekt - Common Lisp, som höll på att färdigställas vid den tiden. Under dessa förhållanden har Franz Inc. kunde inte hitta nya kontrakt, var på väg att stänga och tvingades gå vidare för att utveckla sin egen implementering av Common Lisp - Allegro Common Lisp (namnet valdes för att bevara kontinuiteten i det "musikaliska" temat). Historien om Franz Lisp slutade faktiskt här. Det ursprungliga systemet är nu helt ur bruk.
SchemaSchema-språket utvecklades 1976 vid MIT som en del av Lisp Machine-projektet, en personlig arbetsstation designad helt från hårdvara för att få ut det mesta av Lisp-språket. Inledningsvis var Scheme bara ett "forskningsspråk", under utvecklingen av vilket olika idéer och metoder testades. Målet var att implementera ett minimum av grundläggande funktioner som skulle säkerställa konstruktionen av ett fullfjädrat Lisp-system genom att bygga vidare på denna uppsättning.
Resultatet är en liten och elegant definierad kärna, men mycket effektivt implementerad. Scheme var i synnerhet den första dialekten av Lisp som garanterade optimering av svansrekursion. Språket implementerar en kraftfull makromekanism, förutom listor stöds arrayer som grundläggande konstruktioner. En karakteristisk syntaktisk skillnad mellan Scheme och de flesta Lisp-dialekter är en något annorlunda form av funktionsdefinition. Om varianten används i de flesta dialekter: (DEFUN ИмяФункции (Аргументы) Выражения), så ser den förkortade formen av definitionen i Schema ut som (DEFINE (ИмяФункции Аргументы) (Выражения)). (Nyckelordet och den relativa positionen för funktionsnamnet och argumenten skiljer sig åt). Schema använder dynamisk länkning och implementerar ett enda namnområde för funktioner och variabler, vilket skiljer det från Common Lisp.
Scheme är den enda "gamla" dialekten av Lisp som fortsätter att användas efter den omfattande övergången av Lisp-gemenskapen till den standardiserade Common Lisp. För närvarande finns det flera stödda implementeringar av Scheme, inklusive gratis, det finns exempel på att använda detta språk som ett inbyggt (till exempel används som ett GIMP Tiny-Scheme-skriptverktyg). Flera amerikanska universitet använder Scheme som språk för grundläggande programmeringsundervisning.
ZetalispZetalisp eller "Lisp Machine Lisp" skapades vid MIT under andra hälften av 1970-talet som en del av Lisp Machine Project finansierat av den amerikanska försvarsmyndigheten DARPA.
Systemet var baserat på MacLisp och Emacs-redigeraren, men språket uppdaterades och kompletterades avsevärt, särskilt nya datatyper dök upp i det, Flavours objektorienterade delsystem, där interaktionen mellan program och ett användargränssnitt med flera fönster är baserade, nya direktivstyrningsstrukturer, delvis lånade från Interlisp, funktioner med flera värden (kan returnera mer än ett värde på ett vanligt sätt utan att först "sätta ihop" dem i en behållare), strömmande I/O, namnutrymmen, ett kraftfullt bibliotek funktioner, inklusive matematiska, tillhandahålla vektor- och matrisberäkningar och arbeta med linjära system.
Mycket mer innovation gjordes i själva programmeringssystemet. Systemet designades ursprungligen för att fungera med en grafisk användarterminal och en mus. Den implementerade ett grafiskt användargränssnitt för flera fönster. Systemet inkluderade en Lisp-tolk med flera fönster, en partiell översättare, en Zmacs-textredigerare, en datastrukturinspektör, en debugger, en systemtillståndsutforskare, en systemfilredigerare, en teckensnittsredigerare och en Zmail-e-postklient. Systemet inkluderade översättare av andra högnivåspråk, en omvandlare som ger stöd för Interlisp-program och en uppsättning verktyg på högre nivå. Fortran, Pascal, Ada och Prolog, som levererades som en del av systemet, utvecklades interaktionssätt med Lisp-program, vilket gjorde det möjligt att vid behov utveckla och tillämpa mjukvarusystem på flera språk.
Inledningsvis syftade projektet till att skapa en kommersiell produkt. 1979 skapades två företag - tillverkare av Lisp-maskiner: Symbolics och Lisp Machine Inc. (LMI). Därefter utfördes arbetet med utvecklingen av Zetalisp av dessa företag oberoende. Men även om det fanns vissa skillnader i själva Lisp-maskinerna, var de när det gäller språk nästan helt kompatibla.
NIL och TImplementeringen av MACLisp på VAX-maskinen på själva MIT började 1979. Projektet kallades NIL (samtidigt förkortningen "New Implementation of Lisp" - "New Lisp Implementation" - och standard Lisp-atomen "NIL", vilket betecknar, beroende på användning, logisk icke-sanning eller en tom lista). NIL hade en ganska stor kärna, skriven i VAX assembler, på vilken Lisp-systemet byggdes med samma avlindningsmetod. Till viss del kan NIL betraktas som "svaret på Franz Lisp", eftersom ett av målen med projektet var samma portering av Macsyma-systemet till VAX. NIL lånade mycket från Zetalisp, bland annat Flavours-systemet som gör Lisp-systemet till ett objektorienterat. 1981 bröt gruppen som var inblandad i NIL-projektet upp på grund av oförenliga meningsskiljaktigheter om ideologin för det system som skapades. Trots kollapsen, sedan 1982, har regelbundna uppdateringar av systemet släppts och det har fått en ganska märkbar distribution. På 1980-talet användes NIL ofta i organisationer som hade både VAX- och Lisp-maskiner, eftersom det inte finns några grundläggande ideologiska skillnader mellan NIL och Zetalisp, även om Zetalisp är mycket rikare på funktioner.
En grupp utvecklare som separerade från NIL-projektet började skapa sin egen version av Lisp-systemet, som fick det ironiska namnet " T " (samtidigt - från "True Lisp" - "Real (true) Lisp" och en annan standard Lisp-atom "T", betecknar den logiska sanningen, det vill säga motsatsen till "NIL"). Utvecklingen av denna dialekt genomfördes vid Yale University 1982-1984. Till skillnad från de "gamla" systemen använde T-dialekten statisk variabelbindning som standard, dessutom introducerade dess skapare implementeringen av funktioner som "fullständiga medborgare", vilket innebär att funktioner kan tilldelas variabler utan speciella syntaktiska medel och utan begränsningar och returneras som värden för andra funktioner. T-Lisp hade, till skillnad från NIL, en ganska liten kärna skriven på maskinspråk. Utvecklare använde "spin-up"-tekniken, portade kärnan manuellt till nya plattformar och implementerade resten av systemet direkt i Lisp, med förväntningen att en mycket effektiv översättare skulle ge bättre prestanda för det slutliga systemet än att manuellt implementera en stor maskin språkkärnan.
En kontroversiell punkt i T-Lisp var författarnas beslut att uppdatera och systematisera namnen på systemfunktioner. Så till exempel, namnen på alla predikat utan undantag slutade med ett frågetecken, de "historiskt etablerade" standardnamnen på elementära funktioner ersattes med mnemoniska, motsvarande vad funktionen gör. Till exempel är funktionerna CARoch CDR, som returnerar huvudet respektive svansen på listan, namngivna FIRSToch REST(eng. "första" och "återstående"). Den otvivelaktiga fördelen med detta beslut var underlättandet av inlärningen, den uppenbara nackdelen var oförenlighet med alla andra dialekter i språket. Som ett resultat var skaparna fortfarande tvungna att komplettera systemet med en uppsättning makron som bringar namnsystemet i linje med Common Lisp-standarden. Förvisso ett betydande inflytande som Scheme-dialekten har haft på T. Generellt sett visade sig T-Lisp vara ett ganska enkelt, elegant och mobilt system som implementerades för VAX och portades till många 32-bitars arbetsstationer.
Under första hälften av 1980-talet hade en situation utvecklats i Lisp-samhället som vissa författare jämförde med Babels torn : mer än ett dussin stora dialekter av Lisp existerade och utvecklades parallellt, medan det totala antalet implementeringar var inkompatibla med varandra var betydligt större. En liknande situation observerades vid den tiden i de flesta vanliga programmeringsspråken, men i fallet med Lisp förvärrades situationen av det faktum att språket ursprungligen utformades som godtyckligt utbyggbart, vilket provocerade utvecklingen av dess förmåga i olika dialekter i avsevärt olika riktningar. Om i det inledande skedet, när Lisp nästan uteslutande användes i laboratorier och institut, störde mångfalden av dialekter inte särskilt och var till och med något användbart, eftersom det bidrog till den snabba utvecklingen av språket, sedan på 1980-talet, när det fanns ett behov av industriell utveckling i Lisp, ett överflöd av implementeringar blev en broms, eftersom det ledde till massiv dubblering av utveckling och spridning av krafter för att stödja många Lisp-system.
Försök att standardisera Lisp har gjorts nästan sedan starten (det första förslaget till standardisering går tillbaka till 1960), men på grund av oenighet och betydande skillnader i behoven hos intresserade utvecklingsgrupper accepterades inget av förslagen. Under andra hälften av 1970-talet gjorde det amerikanska försvarsdepartementet ett bra jobb med att analysera situationen inom militär mjukvaruutveckling, varefter man anordnade en tävling för att utveckla ett nytt högnivåspråk för inbyggda system, som blev Ada-språket . Ada var dock ursprungligen inte avsedd för artificiell intelligens och karaktärsbearbetning, vilket ledde till att den amerikanska militären tvingades tillåta att ett mer lämpligt språk används för sådan utveckling. Därför gav USA:s försvarsdepartement organisatoriskt och ekonomiskt stöd för bildandet av en industriell standard för språket Lisp, som det antog som ett extra verktyg för att utveckla mjukvara för militära applikationer.
Det ursprungliga utkastet till standarden började vid Carnegie Mellon University på grundval av ett internt Spice Lisp-projekt, som också ursprungligen syftade till att utveckla ett Lisp-system för arbetsstationen. Redan från början fick den projicerade standarden namnet "Common Lisp" ("Common Lisp"), vilket betonade utvecklingsmålet - att få ett enda basspråk, på grundval av vilket det skulle vara möjligt att skapa programvarukompatibla system. Ett 80-tal specialister från amerikanska universitet, laboratorier och företag deltog i utvecklingen och redigeringen av standarden. För första gången skedde utvecklingsprocessen på distans, via datornätverket ARPANET , genom vilket över 3 000 meddelanden överfördes. Standardutvecklingsprocessen avslutades 1984. Hans resultat spelades in i den första upplagan av Guy Steeles Common Lisp: the Language.
Tillkomsten av Common Lisp saktade ner skapandet av nya dialekter av språket. De "gamla" dialekterna fortsatte att existera, men i takt med att plattformarna de körde på gick ur bruk så föll även motsvarande Lisp-system. De flesta av dem upphörde att existera 1985-1995. Nya utvecklingar har redan gjorts i Common Lisp. Men under de följande åren dök flera nya Lisp-dialekter upp, varav de flesta följde förenklingens väg och var orienterade mot mikrodatorer.
ISLISPISLISP är en Lisp-specifikation som utvecklades på 1990-talet och publicerades av ISO 1997 [ 8] . Specifikationen uppdaterades 2007 [9] . ISLISP är ett försök att standardisera kärnan i Lisp genom att konsolidera befintliga och utveckla kommersiella Lisp-dialekter vid tiden för dess tillkomst. Dialekten liknar på många sätt Common Lisp (lexikalisk omfattning, separata namnområden för funktioner och variabler, ganska kraftfullt datatypsystem, stöd för komplexa typer, makrosystem, objektsystem), men mindre i omfattning. För 2018 finns det ungefär ett dussin större implementeringar av ISLISP, släppta huvudsakligen under proprietära licenser.
openlispEn dialekt skapad av Christian Julien 1988. Ursprungligen kallad MLisp, döptes det om till OpenLisp 1993. Namnet symboliserar användningen av öppna standarder, men har ingenting att göra med Open Source Initiative eller fri programvara : systemet distribueras under en egen licens.
Överensstämmer helt med ISLISP-specifikationen , implementerar dessutom ett antal funktioner som saknas i denna standard. Interaktiv utveckling ( REPL ) är möjlig i Emacs- miljön . Förutom tolken innehåller systemet en kompilator som konverterar källkoden till LAP (Lisp Assembly Program, assembly-liknande lågnivåkod i formatet Lisp-listor), och en kodgenerator som kompilerar LAP-programmet till källkod på C- språket . Mycket uppmärksamhet ägnas åt interaktion med C/C++ och Java-kod, stöd för inbäddning i mjukvarusystem som en inbäddad språktolk. Systemet fortsätter att utvecklas och stöds, det finns versioner för de flesta tillgängliga operativsystem och hårdvaruplattformar.
Pico LispPicoLisp är en gratis implementering av Lisp designad för användning på Linux och andra POSIX -system . Projektet dök upp i slutet av 1980-talet, dess mål var att skapa ett minimalistiskt men ändå praktiskt Lisp-system för persondatorer.
Från språksidan är PicoLisp skiftlägeskänslig, stöder UTF-8 och är extremt enkel. Kärnan stöder bara tre datatyper: siffror, strängar och listor. Syntaktiska medel har införts för att kontrollera parametrarnas beräkningsbarhet, citatformuläret har utökats till ett obestämt antal parametrar. Denna lösning eliminerade behovet av en speciell syntax för makron och ett lambda-uttryck. Strukturer och arrayer stöds inte, det finns ett ekonomiskt utfört, men kraftfullt objektsubsystem. Till skillnad från Common Lisp använder språket dynamisk parameterbindning.
PicoLisp-miljön har ingen kompilator (detta är ett grundläggande beslut, på grund av vilket många förenklingar gjordes i språket), men den inkluderar en inbyggd applikationsserver och lagringsundersystem [10] . Implementerade ett direktanrop till externa funktioner skrivna i C, samt interaktion med Java-kod. Dialekten fortsätter att utvecklas, nya versioner av programmeringsmiljön för flera plattformar släpps regelbundet.
EuLisp
En dialekt utvecklad sedan 1985 av en gemenskap av europeiska Lisp-utvecklare och användare från akademi och industri. Det kan ses som ett slags "europeiskt svar på Common Lisp" - ett alternativt försök att skapa en enda dialekt av Lisp som lämpar sig för en lång rad uppgifter. Målet med projektet var att skapa ett effektivt, kompakt och obehindrat "Lisp past"-språk. En av prioriteringarna i utvecklingen av detta projekt var att lägga till objektorienterade funktioner till Lisp.
Dialekten stöder definitionen av moduler med lexikal omfattning, stängningar med dynamisk bindning, en enda namnrymd för variabler och funktioner, som i Scheme, inbyggt stöd för samtidighet, ett objektsystem med enkel och multipel arv. En funktion i projektet är uppdelningen av språket i två nivåer, nivå-0 och nivå-1, vissa funktioner är endast tillgängliga på nivå 1, till exempel multipelt arv och metaobjekt.
Den senaste officiella specifikationen (version .99) släpptes 1993, dess inofficiella revision (version .991) 2010. Den första tolken släpptes 1990, på 1990-2000-talet skapades flera implementeringar, vars utveckling upphörde 2011.
newLispEn dialekt utvecklad 1991 av Lutz Müller för användning som ett skriptspråk på Sun-arbetsstationer som kör SunOS och FreeBSD. För närvarande tillgänglig på 32-bitars och 64-bitars Intel-plattformar under FreeBSD, Linux, Windows, Mac. Skiljer sig i enkelhet, liten volym, dynamisk omfattning av variabler, har ett antal funktioner i syntax. Stöder FOOP-objektsystemet, kommunikationsverktyg mellan processer och mer. I miljön finns en tolk, en mini-IDE med kodredigerare och en terminalemulator för interaktiv utveckling, bibliotek för webbutveckling och nätverk via TCP- och UDP-protokoll.
RacketUtvecklat sedan 1994 av PLT Inc. en dialekt som ursprungligen hette PLT Scheme. Det är en ättling till Scheme-dialekten, men utökar den avsevärt. Ett av målen med att skapa Racket var att tillhandahålla en plattform för utveckling och implementering av domänspecifika språk. Dess karakteristiska egenskap är ett mycket kraftfullt makrosystem som låter dig skapa nya syntaktiska konstruktioner och till och med språk. Samtidigt säkerställer modulsystemet användningen i ett enda program av element skrivna på olika dialekter med olika semantik.
Implementeringen inkluderar en kompilator, ett runtime-system, en JIT-kompilator, en integrerad utvecklingsmiljö med en uppsättning verktyg, bibliotek. DrRacket IDE, skriven i Racket själv, innehåller en profilerare, debugger och enhetstestningssystem. Det finns bibliotek som stödjer system- och nätverksprogrammering, webbutveckling, ett enda gränssnitt till operativsystemet, ett gränssnitt för anrop av externa funktioner, flera varianter av reguljära uttryck, parser- och parsergeneratorer, logiska programmeringsverktyg och ett avancerat grafiskt användargränssnitt. Plattformen är implementerad för Windows, MacOS, Linux och andra varianter av UNIX. Den distribueras som gratis och öppen källkod under GNU Lesser General Public License (LGPL). Ett centraliserat arkiv upprätthålls för paket och tillägg skapade av communityn.
Det används som forskning (främst som en plattform för att utveckla språk och programmeringsverktyg), utbildning, skript , industrispråk (i synnerhet för att utveckla videospel). I handledningen använder handledningen Bootstrap i konceptet "lära genom att koda spel".
ArcArc är en dialekt skapad av Paul Graham . Målet med projektet som förklarats av författaren är att skapa ett enkelt, byggt på en minimal uppsättning ekonomiskt definierade enheter, Lisp-system med en uppsättning praktiskt användbara bibliotek, fokuserat på professionell användning och möjliggör effektiva "Lisp-hack" (olika beräkningsknep) baserat på funktionerna hos Lisp). Författaren vägrade i princip att stödja vissa tekniker i Arc, i synnerhet OOP , eftersom han ansåg att de bara behövs när man utvecklar inom stora organisationer och i sig inte ger någon verklig användbar effekt. Utvecklingen tillkännagavs 2001, den första offentliga versionen dök upp 2008. Den första implementeringen av språket skrevs i Racket-miljön. Sedan 2009 har det ursprungliga systemet praktiskt taget upphört att utvecklas, och nu fortsätter utvecklingen av Arc i flera gafflar .
Under de senaste decennierna har språk som använder automatisk minneshantering, kompilering till mellankod och dess exekvering i en virtuell maskin, som Java, Python, C# och andra, blivit utbredda. Flera dialekter av Lisp har också skapats, orienterade mot utförande i andra språks dynamiska miljöer. Dessa dialekter kan arbeta direkt med biblioteken i motsvarande språkmiljö och interagera med program på andra språk som körs i samma miljö. Bland dem:
I grund och botten var de ideologiska grunderna för standarden influerade av MACLisp och dess dialekter, ett stort antal funktioner lånades från InterLISP och nya system som Zetalisp och NIL.
Common Lisp är ett språk med statisk variabelbindning, traditionell representation av funktioner (funktioner är inte "fullständiga medborgare"), stöder makron, funktionaler, lexikaliska stängningar. Det vill säga, ur den funktionella delen av språkets synvinkel innehåller den hela uppsättningen av syntaktiska medel som har utvecklats i Lisp under det föregående kvartssekelet och är tillräckligt för all tillämpning av funktionell programmering och språkutvidgning i alla önskad riktning. Systemfunktioner i Common Lisp behåller sina traditionella namn, men många av dem har synonymer med mer beskrivande namn, t.ex. funktionerna CAR(att få huvudet på en lista) och CDR(att få svansen på en lista) har synonymer för FIRST("första" ) respektive REST("återstoden") .
Eftersom målet var att utveckla ett system som lämpar sig för bredast möjliga användningsområde utökas specifikationen avsevärt med funktioner, syntaktiska medel och mekanismer som inte är karakteristiska för originalet Lisp. Så till exempel har nästan alla syntaktiska konstruktioner som finns i imperativa språk, inklusive flera typer av loopar, lagts till språket. Objektsystemet CLOS (Common Lisp Object System) ingick ursprungligen inte i standarden, men blev en del av det senare. Common Lisp lämpar sig för att skriva program i både funktions- och direktivstil, det går att generalisera programmering (med standardmakron), produktionsprogrammering, det finns verktyg för att organisera logik, objektprogrammering och datadriven programmering. Specifikationen innehåller inte en detaljerad beskrivning av programmeringsmiljön, utan definierar endast i de mest allmänna termerna dess sammansättning och principer för interaktion mellan element.
Kritiker av den nya standarden pekade på dess uppsvälldhet och överbetoning av praktiska krav, vilket ledde till en kränkning av den "funktionella renheten" hos Lisp och en ökning av storleken på Lisp-systemet. Ändå, under påtryckningar från det amerikanska försvarsdepartementet och delvis med dess ekonomiska stöd, skapades Common Lisp-implementeringar under andra hälften av 1980-talet för nästan alla vanliga plattformar.
En större revidering av standarden, publicerad 1984, ägde rum 1990 :
1995 standardiserades Common Lisp av ANSI . Standarden upprepade praktiskt taget 1990 års specifikation, ändringarna är små och består huvudsakligen av tillägg, borttagning och byte av operatörer och systemvariabler och ändringar i systemanrop. Vi kan notera utseendet i Common Lisp av typen boolean (boolean), vars värden bara kan vara NIL och T.
Ett exempelprogram som visar meddelandet " Hej, värld!" »:
( format t "Hej världen!~%" )Variants of Quine (ett program som matar ut sin källkod) i Lisp:
(( lambda ( x ) ( lista x ( lista 'citat x ))) ( citat ( lambda ( x ) ( lista x ( lista 'citat x )))))) (( lambda ( x ) ( lista x ( lista 'citat x ))) ' ( lambda ( x ) ( lista x ( lista 'citat x )))))Båda fungerar i de flesta Lisp-dialekter, inklusive Scheme . Vilken av dem som kommer att vara mer exakt beror på implementeringen av Lisp-systemet: i vissa, när du visar ett listvärde för att visa blockeringen av beräkningen, quotevisas den speciella operatören som ett fullständigt namn (det första alternativet är lämpligt för dem) , i andra - som en apostrof (det andra alternativet). Quine's Common Lisp -version med backquote:
(( lambda ( x ) ` ( , x ',x )) ' ( lambda ( x ) ` ( , x ',x )))En iterativ version av funktionen för att bestämma det N:te Fibonacci-talet med hjälp av Loop-makrot:
( defun fibonacci ( n ) ( loop upprepa n för a = 0 sedan b och b = 1 sedan ( + a b ) slutligen ( returnera b )))Rekursiv version av den N:te Fibonacci-nummerfunktionen:
( defun fibonacci ( n ) ( if ( > n 1 ) ( + ( fibonacci ( - n 1 )) ( fibonacci ( - n 2 ))) n ))Rekursiv funktion för att beräkna en godtycklig heltalspotens (algoritm med logaritmisk exekveringstid och rekursionsdjup):
( defun power ( x n ) ( cond (( minusp n ) ( / 1 ( power x ( - n )))) (( noll n ) 1 ) (( evenp n )( power ( * x x ) ( / n 2 ))) ( t ( * x ( effekt ( * x x ) ( / ( - n 1 ) 2 ))))))Här används systempredikat ZEROP - kontrollera om det är lika med noll, MINUSP - kontrollera för negativitet, EVENP - kontrollera för paritet.
1955 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2018 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Lisp 1.5 | Lisp 1.5 | ||||||||||||||||||||
Maclisp | Maclisp | ||||||||||||||||||||
Interlisp | Interlisp | ||||||||||||||||||||
ZetaLisp | Lisp Machine Lisp | ||||||||||||||||||||
Schema | Schema | ||||||||||||||||||||
NOLL | NOLL | ||||||||||||||||||||
Vanlig Lisp | Vanlig Lisp | ||||||||||||||||||||
LeLisp | Le_Lisp | ||||||||||||||||||||
T | T | ||||||||||||||||||||
Emacs Lisp | Emacs Lisp | ||||||||||||||||||||
AutoLISP | AutoLISP | ||||||||||||||||||||
openlisp | openlisp | ||||||||||||||||||||
Pico Lisp | Pico Lisp | ||||||||||||||||||||
EuLisp | EuLisp | ||||||||||||||||||||
ISLISP | ISLISP | ||||||||||||||||||||
ny LISP | ny LISP | ||||||||||||||||||||
racket | racket | ||||||||||||||||||||
Svek | GNU Guile | ||||||||||||||||||||
Visuell LISP | Visuell LISP | ||||||||||||||||||||
Clojure | Clojure | ||||||||||||||||||||
Båge | Båge | ||||||||||||||||||||
LFE | LFE | ||||||||||||||||||||
Hy | Hy |
Omfattningen av Lisp-språket är varierande: vetenskap och industri, utbildning och medicin, från avkodning av det mänskliga genomet till flygplansdesignsystemet. De första tillämpningsområdena för Lisp-språket var förknippade med symbolisk databehandling och beslutsprocesser. Den mest populära dialekten av Common Lisp idag är ett universellt programmeringsspråk. Det används ofta i en mängd olika projekt: Internetservrar och tjänster, applikationsservrar och klienter som interagerar med relations- och objektdatabaser, vetenskapliga beräkningar och spelprogram.
Det finns specialiserade dialekter av Lisp designade för specifika applikationer, till exempel skapades Game Oriented Assembly Lisp (GOAL) för att skriva mycket dynamiska tredimensionella spel, hela Jak och Daxter -serien av spel är skrivna i den .
En av användningsområdena för Lisp är dess användning som ett skriptspråk som automatiserar arbete i ett antal applikationsprogram, inklusive:
När det gäller Lisp är det svårt att dra en tydlig gräns mellan en dialekt och ett ättlingspråk, eftersom olika dialekter av Lisp, skapade under mer än ett halvt sekel av dess existens, kan skilja sig väsentligt och vara oförenliga. Å andra sidan har Lisp, helt enkelt i kraft av sin ålder, haft ett eller annat inflytande på ett stort antal språk, och inte bara funktionella. Om vi betraktar de direkta ättlingarna till Lisp endast språk som har behållit programmets allmänna struktur, men som är syntaktiskt inkompatibla med Lisp, så kan vi skilja:
I början av 1970-talet erkändes de begränsningar som tidsdelningssystemet införde för användare av interaktiv programvara (som inkluderar både Lisp-system och de flesta program skrivna i Lisp). Dessutom är Lisp relativt dyrt för dynamiskt stöd, inklusive typkontroll av körtid och periodisk sophämtning. 1973 uppstod idén att utveckla en persondator (arbetsstation), designad, med utgångspunkt från hårdvaran, specifikt för att uppnå den mest effektiva exekveringen av Lisp-program, inklusive hårdvarustöd för lambda-beräkningar och dynamisk typning.
I USA ägde Lisp datorutveckling rum på 1970-talet vid Xerox Corporations Palo Alto Research Center och vid MIT (det senare sponsrat av DARPA ). Deras resultat var uppkomsten i början till mitten av 1980-talet av tre stora tillverkare: Xerox, Lisp Machine Inc. (LMI) och Symbolics Inc. Xerox tillverkade Lisp-maskiner som stödde Interlisp, de två sista företagen kom från MIT och fokuserade på Zetalisp. Lite senare tog Texas Instruments över produktionen av Lisp-maskiner . I Japan, 1984, visades den första prototypen av Fujitsus kommersiella Alpha lisp-maskin .
Lisp-maskiner hade en hårdvaruarkitektur fokuserad på listbearbetning och funktionell programmering, med hårdvarustöd för sophämtning, dynamisk typning. De hade integrerade utvecklingsmiljöer som innehöll tusentals funktioner och inklusive alla komponenter som för närvarande utgör högnivåspråks- IDE:er . Grafiskt användargränssnitt med flera fönster som stöds , arbeta med musen och andra ytterligare positioneringsverktyg ( styrkula , ljuspenna ), högkvalitativ I/O-grafik och ljud. Även om de var Lisp-orienterade, var andra högnivåspråk också tillgängliga i Lisp-maskiner och tillhandahöll medel för interoperabilitet över flera språk. Lisp tillhandahöll både arbete i tolkat läge och kompilering av program till objektkod.
För sin tid var Lisp-maskiner bland de mest kraftfulla datorerna i klassen för personliga arbetsstationer. De förutspåddes ha en stor framtid, men på 1990-talet förföll de alla, och tillverkarna lade antingen ner sin verksamhet eller omorienterade sig till produktionen av datorer för allmänt bruk. Anledningen var att i samband med en lång exponentiell tillväxt i datorers hastighet och minne visade sig utvecklingen av utrustning "under språket" vara meningslös - snabbt utvecklande allmändatorer utrustade med Lisp-översättare gick om Lisp-maskiner i deras förmågor, som på grund av sin specialisering var dyrare och förlorade i mångsidighet.
I Sovjetunionen blev arbetet relaterat till användningen av Lisp och skapandet av deras egna Lisp-system mer aktivt efter 1968, då en grupp amerikanska vetenskapsmän, bland vilka McCarthy och B. Berkeley[ förtydliga ] besökte Sovjetunionen. I Novosibirsk, vid Computer Center of the Siberian Branch of the Academy of Sciences, där McCarthy tillbringade större delen av sin tid, lade han grunden för implementeringen av Lisp på BESM-6 . I Moskva, vid Computing Center vid USSR Academy of Sciences, började sovjetiska matematiker Lavrov och Silagadze , med hjälp av Berkeley, arbeta på sin egen version av Lisp-tolken för BESM-6. Därefter gick Lavrov till jobbet vid Leningrad State University och Silagadze - vid Computing Center för Georgian Academy of Sciences i Tbilisi, där de fortsatte att arbeta med Lisp och deltog i skapandet av flera Lisp-system för ES-datorer . [elva]
Ett Lisp-system för den polska datorn Odra 1204 skapades i Leningrad, en implementering för BESM-6 kompatibel med den engelska versionen av Lisp för ICL 4-datorn skapades i Moskva, implementeringar för ES-datorn dök upp på MPEI och Far Eastern Scientific Center i Vladivostok. Vid Institute for Information Transmission Problems (Moskva) i slutet av 1970-talet skapades EKLISP-lisp-systemet för ECLIPS-minidatorn. Västerländska datorer i Sovjetunionen använde Stanford Lisp och UT-Lisp (Dubna, IBM 370 och CDC 6600). Populärt var också det svenska Nordströmsystemet (Lisp i Fortran).
1975 ägde den fjärde internationella konferensen om problemen med artificiell intelligens IJCAI-75 rum i Tbilisi, vilket bidrog till att öka intresset för Lisp och sprida det till universitet och forskningsinstitut. 1978 publicerades den första Lisp-läroboken på ryska av Svyatoslav Lavrov och Givi Silagadze ("Automatisk databehandling. LISP-språket och dess genomförande").
På 1980-talet fortsatte intresset för Lisp i Sovjetunionen, men mycket lite litteratur om språket publicerades (två böcker publicerades på ett decennium, båda översatta: "Functional Programming. Application and Implementation" av Henderson, översatt 1983, och en tvådelad "The World of Lisp" av Hyvönen och Seppänen, vars översättning utkom 1990).
I det postsovjetiska Ryssland är användningen av Lisp mestadels begränsad till akademisk forskning och enskilda entusiasters arbete. Dessutom fortsätter Lisp att användas i utbildningssyfte vid vissa ryska universitet, men även här på senare år har det blivit märkbart trångt: som ett allmänspråkigt språk lärs det inte ut och används inte, och yngre studenter föredrar ofta att använda det som utbildningsspråk för undervisning i funktionell programmering. funktionella språk som har dykt upp under de senaste två decennierna. Ändå kvarstår intresset för språket, vilket framgår av uppkomsten av översatta och originaltryckta verk på Lisp, som återupptogs under 2010-2020-talet [12] .
Läspa | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Egenskaper |
| ||||||||||||||
Genomföranden |
| ||||||||||||||
Hårdvara |
| ||||||||||||||
gemenskap |
| ||||||||||||||
|
Programmeringsspråk | |
---|---|
|