Lisp (език за програмиране)

от Уикипедия, свободната енциклопедия
Направо към: навигация, търсене

Lisp (исторически, LISP ) от семейство на компютърни езици за програмиране с дълга история и отличителен, напълно скоби префикс нотация .  Първоначално определен през 1958 г., Lisp е вторият най-стар език на високо равнище програмиране в широка употреба днес. Само Fortran е по-стар, с една година.  Lisp е променен от ранните си дни, и много диалекти са се появили през неговата история. Днес, най-известните с общо предназначение Lisp диалекти са  CommonLisp  и  Scheme .

Lisp първоначално е бил създаден като практическa математически нотация за компютърни програми , повлиянa от нотацияta на Alonzo Church- Lambda calculus . Той бързо се превръща в предпочитан език за програмиране за изкуствен интелект (AI) . Като един от най-ранните програмни езици, Lisp пионира много идеи от компютърните науки , включително структури дърво данни , автоматично управление на съхранението , динамично типизиране , условни , функции с по-висок ред , рекурсия , както и самостоятелен хостинг компилатора .

Името LISP произлиза от "Списък на процесора".  Свързани списъци са един от основните структури от данни на Lisp, и Lisp изходния код се извежда на списъци. По този начин, Lisp програми могат да манипулират изходния код като структура от данни, въз основа на макро системи, които позволяват на програмистите да създават нов синтаксис или нови специфични езикови домейни вградени в Lisp.

Взаимозаменяемостта на кода дава на Lisp моментално разпознаваем синтаксис. Всички програмен код е написан като S-изрази , или скоби списъци. Функция повикване или синтактичната форма е написана под формата на списък с функцията или името на оператора на първо място, и аргументите след това; например, една функция f, която отнема три аргументи ще бъдат призовани като .(f arg1 arg2 arg3)

История

Lisp е изобретен от Джон Маккарти през 1958 г., докато е бил в Масачузетския технологичен институт (MIT). McCarthy публикува своя дизайн на хартия в съобщенията на ACM през 1960 г., озаглавена "повтаряща Функции символично изразяване и им Изчислената от машина, част I". Той показа, че с няколко прости оператори и нотация за функции, може да се изгради на Тюринг-пълна език за алгоритми.

Обработка на информация Език беше първият AI език, от 1955 г. или 1956 г., и които вече са включени много от концепциите, като например списък обработка и рекурсия, които дойдоха, за да бъдат използвани в Lisp.

Оригиналната нотация Маккарти използва скоби " М-изрази ", които ще бъдат преведени на S-изрази . Като пример, М-експресията car[cons[A,B]]е еквивалентна на S-експресията . След като Lisp се реализира, програмисти бързо избрали да използвате S-изрази, и М-изрази са били изоставени. М-изрази отново се появиха с краткотрайни опити на MLISP  от Хорас Enea и CGOL от Vaughan Прат .(car (consA B))

Lisp е въведена за първи път от Стив Ръсел на IBM 704 компютъра. Ръсел е чел хартия Маккарти и реализирани (за изненада на Маккарти), че Lisp Оценка функция може да се изпълнява в машинен код .  В резултат на работна Lisp интерпретатор, който може да се използва за изпълнение на Lisp програми, или по-правилно ", оцени Lisp изрази."

Две монтаж езикови макроси за IBM 704 станаха примитивните операции за разлагането на списъци: car(съдържание на Адрес част на номер от регистъра) и cdr(съдържание на Намаляване част на номер от регистъра).  От контекста, то е ясно, че терминът "регистър" се използва тук, за да кажа "памет регистър", в днешно време се нарича "място на паметта". Lisp диалекти все още използват carи cdr/ к ɑːr / и / к ʊ г ər / ) за операциите, които се връщат на първия елемент от списъка и на останалата част от списъка, съответно.

Първата пълна Lisp компилатора, написани на Lisp, беше въведена през 1962 г. от Тим Харт и Майк Левин в Масачузетския технологичен институт.  Този компилатор въведе Lisp модел на частичното компилация, в която компилира и тълкува функции могат да се смесят свободно. Езикът, използван в Харт и Левин бележка е много по-близо до съвременния Lisp стил, отколкото по-рано код Маккарти.

Lisp беше трудна система за изпълнение с компилатора техники и склад хардуера на 1970 г. в. Събирането на боклука съчетания, разработен от тогавашния MIT студент Даниел Едуардс , направени то практически да тече Lisp на компютърни системи с общо предназначение, но ефективност все още е проблем. Редактиране ] Това доведе до създаването на Lisp машини : специализиран хардуер за тичане Lisp среди и програми. Напредъкът в двете компютърен хардуер и съставител технология скоро направени Lisp машини остаряла. Редактиране ]

През 1980-те и 1990-те години, голямо усилие е направено, за да се уеднакви работата по нови Lisp диалекти (най-вече наследници да Maclisp като ZetaLisp и NIL (New Изпълнение на Lisp)) в един-единствен език. Новият език, обща Lisp , е малко по-съвместим с диалектите го заменят (книгата Общата Lisp езика отбелязва съвместимостта на различни конструкции). През 1994, ANSI публикувани стандарта Общата Lisp, "ANSI X3.226-1994 информационните технологии програмен език Общата Lisp

Синтаксис[редактиране | редактиране на кода]

Символичните изрази (S-изрази) [ редактиране източник ][редактиране | редактиране на кода]

Lisp е израз ориентиран език . За разлика от повечето други езици, не се прави разлика между "изрази" и "отчети" ; Съмнителен - обсъдят ] целия код и данните се записват като изрази. Когато израз се оценява , то произвежда стойност (в Общата Lisp, може би няколко стойности), който след това може да се вгражда в други изрази. Всяка стойност може да бъде всеки тип данни.

1958 хартия Маккарти въвежда два вида синтаксис: Символични изрази ( S-изрази , sexps), които отразяват вътрешния представителството на код и данни; и Мета изрази ( М-изрази ), които изразяват функции на S-изрази. М-изрази никога не намерили подкрепа, и почти всички Lisps днес работа с S-изрази, за да манипулират код както и данни.

Използването на скоби е най-непосредствено очевидна разлика Lisp е от другите езици за програмиране семейства. В резултат на това учениците са отдавна дадени Lisp прякори като губи в Stupid скоби , или много Дразни Излишно скоби .  Въпреки това, синтаксиса на S-израз също е отговорен за голяма част от властта Lisp е: синтаксиса е изключително редовен, което улеснява манипулирането чрез компютър. Въпреки това, синтаксиса на Lisp не се ограничава до традиционните скоби формат. Тя може да бъде разширен, за да включва алтернативни обозначения. Например, XMLisp е общата Lisp разширение, което наема на протокола metaobject да се интегрират S-изрази с Extensible Markup Language ( XML ).

The разчитането на изразяване дава език голяма гъвкавост. Тъй като Lisp функции са написани като списъци, те могат да бъдат обработени точно като данни. Това позволява лесно писане на програми, които манипулират други програми ( metaprogramming ). Много Lisp диалекти използват тази възможност, с помощта на макро системи, което позволява разширение на езика почти без лимит.

Списъци [ редактиране източник ][редактиране | редактиране на кода]

А Lisp списък е написана с неговите елементи, разделени от празно пространство, и заобиколен от скоби. Например, има списък кои елементи са три атома , , и . Тези стойности са имплицитно напечатани: те са съответно две цели числа и Lisp-специфичен тип данни, наречен "символ", и не е нужно да се декларира като такъв.(1 2 foo) 12foo

Празното списъка ()също е представена като специален атом nil. Това е единственият субект в Lisp който е едновременно един атом и един списък.

Изрази са написани като списъци, като се използва префикс нотация . Първият елемент в списъка е името на функцията, името на макро, а израз ламбда или на името на "специален оператор" (виж по-долу). Останалата част от списъка, са аргументите. Например, функцията listвръща аргументи си като списък, така че изразът

 ( Списък  1  2  ( цитат  Foo ))

оценява в списъка . В "цитат" Преди в предишния пример, е "специален оператор", който се връща аргумента си, без да го оценяване. Всякакви некотирани изрази са рекурсивно оценени преди изразяването на обвивката е оценена. Например,(1 2 foo)foo

 ( Списък  1  2  ( списък  3  4 ))

оценява в списъка . Имайте предвид, че третият аргумент е списък; списъци могат да бъдат вложени.(1 2 (3 4))

Операторите [ редактиране източник ][редактиране | редактиране на кода]

Аритметични оператори се третират по същия начин. изразът

 ( +  1  2  3  4 )

оценява до 10 еквивалент под въвирам нотация ще бъде " ".1 + 2 + 3 + 4

Lisp е без понятие от операторите като реализирани в Algol-производни езици. Аритметични оператори в Lisp са variadic функции (или п-ри ), в състояние да вземе произволен брой аргументи. A C-стил "++" нарастване оператор понякога се осъществява под името incf даване синтаксис

 ( Incf  х )

, Еквивалентен на (setq х (+ х 1)) , връщане на новата стойност на х .

"Специални оператори" (понякога наричани "специални форми") осигуряват контрол структура Lisp е. Така например, специален оператор ifотнема три аргумента. Ако първият аргумент е не-нула, то оценява на втория аргумент; в противен случай, това се оценява към третия аргумент. По този начин, изразът

 ( Ако  нула 
     ( списък  1  2  "Foo" ) 
     ( списък  3  4  "бар" ))

оценява на . Разбира се, това би било по-полезно, ако не е тривиална израз е бил заместен на мястото на .(3 4 "bar")nil

Lisp предвижда също логически оператори и , или и не . На и и или операторите да направят оценка на късо съединение и ще се върнат първия си аргумент не-нула.

 ( Или  ( и  "нула"  нула  "никога" )  "Джеймс"  "задача  " време )

ще оцени до "Джеймс".

Lambda изрази и функция определение [ редактиране източник ][редактиране | редактиране на кода]

Друг специален оператор, lambdaсе използва да свърже променливи до стойности, които след това се оценяват в израз. Този оператор се използва и за създаване на функции: аргументите да lambdaса списък от аргументи, а изразът или изрази, за които се оценява функция (върнатата стойност е стойността на последния израз, който се оценява). изразът

 ( Ламбда  ( Arg )  ( +  Arg  1 ))

оценява към функция, която, когато се прилага, приема само един аргумент, той се свързва с argи връща броя един по-голям от този довод. Lambda изрази са третирани не по-различно от именувани функции; те се позовават по същия начин. Следователно, изразът

 (( Ламбда  ( Arg )  ( +  Arg  1 ))  5 )

оценява на 6.

Named функции са създадени от съхраняване на изразяване ламбда в символ с помощта на defun макроса.

 ( Defun  Foo  ( а  б  в  г )  ( +  а  б  в  г ))

(defun f (a) b...)дефинира нова функция наречена fв глобалната среда. Концептуално е подобно на уравнение:

 ( Setf  ( fdefinition  "е )  #" ( ламбда  ( а )  ( блок  е  б ... )))

Атомите [ редактиране източник ][редактиране | редактиране на кода]

В оригиналния LISP имаше две основни типове данни : атоми и списъци. Списъкът беше ограничен подредена последователност от елементи, където всеки елемент е или атом или списък, и един атом е номер или символ. Символ е по същество едно уникално име елемент, написана като буквено-цифров низ в изходния код , и използван като име на променлива или като елемент от данни в символичен обработка . Например, списъкът съдържа три елемента: Foo на символ, списъкът , и номер 2.(FOO (BAR 1) 2)(BAR 1)

Съществената разлика между атоми и списъци е, че атомите са неизменни и уникални. Два атома, които се появяват на различни места в изходния код, но са написани по абсолютно същия начин, представени от един и същ обект, цитиране необходими ] докато всеки списък е отделен обект, който може да бъде променен, независимо от другите списъци и могат да бъдат разграничени от други списъци от оператори сравнение.

Тъй като все повече типове данни са въведени в по-късните Lisp диалекти, и програмни стилове еволюирали, концепцията на атома загубили значение. Редактиране ] Много диалекти все още запазват предикатното атом за наследство съвместимост , цитиране необходими ] определяне то важи и за всеки обект, който не е против.

Conses и списъци [ редактиране източник ][редактиране | редактиране на кода]

Основна статия: Против Box-а-показалка схема за списъка (42 69 613) А Lisp списък се поединично свързан . Всяка клетка от този списък се нарича минуси (в схемата, а чифт ), и се състои от две насоки , наречен колата и CDR . Това са съответно еквивалентни на dataи nextобластта обсъдени в статията списъка свързан .

От много структурите от данни, които могат да бъдат изградени от минуси клетки, един от най-основните, се нарича правилна списък . А правилното списък е или специална nil(празен списък) символ или минуси, в която carсочи към една данна (който може да бъде друг минуси структура, като например списък), и cdrсочи към друг надлежен списък.

Ако даден минуси се вземат, за да бъде глава на свързан списък, след това си автомобили точки към първия елемент от списъка, както и неговите CDR точки към останалата част от списъка. Поради тази причина, carи cdrфункции се наричат също firstи restкогато се отнася до conses които са част от свързан списък (по-скоро, отколкото, да речем, едно дърво).

По този начин, Lisp списък не е атомен обект, като например на един клас контейнер в C ++ или Java ще бъде. Списъкът не е нищо повече от съвкупност от свързани conses. Променлива, която се отнася до даден списък е просто указател към първите минусите в списъка. Traversal на списък може да бъде направено от cdring надолу в списъка; че е, като последователни CDR, за да посетят всеки минуси на списъка; или с помощта на някоя от няколко функции по-висок ред за карта функция над списък.

Защото conses и списъци са толкова универсални в Lisp системи, това е често срещано погрешно схващане, че те са единствените структури от данни Lisp е. В действителност, всички, но най-опростени Lisps има и други структури от данни, като вектори ( масиви ), хеш таблици, структури, и така нататък.

S-изрази представляват списъци [ редактиране източник ][редактиране | редактиране на кода]

Скоби S-изрази представляват свързан списък структури. Има няколко начина да представляват същия списък като S-израз. А минуси могат да бъдат написани на пунктирана-чифт нотация като , където е колата и ДРК. А вече правилното списък може да бъде написана в пунктирана-чифт нотация. Това обикновено се съкращава като в списъка за означаване . Неправилната списък  може да бъде написана в комбинация от двете - както за списъка на три conses чието последно CDR е (т.е., в списъка в напълно определен вид).(a . b)ab(a . (b . (c . (d . nil))))(a b c d)(a b c . d)d(a . (b . (c . d)))

Процедури Списък обработка [ редактиране източник ][редактиране | редактиране на кода]

Lisp осигурява много вградени процедури за достъп и контрол на списъци. Списъци могат да се създават директно с listпроцедурата, която отнема произволен брой аргументи, и се връща в списъка на тези аргументи.

 ( Списък  1  2  "с  3 ) 
 ; Output: (1 2 3)
 ( Списък  1  " ( 2  3 )  4 ) 
 ; Output: (1 (2 3) 4)

Поради начина, по който списъци са изградени от минуси двойки , на consпроцедурата може да се използва за добавяне на елемент към предната част на списъка. Имайте предвид, че consпроцедурата е асиметрично в начина, по който обработва списък аргументи, защото за това как са построени списъци.

 ( Минуси  1  " ( 2  3 )) 
 ; Output: (1 2 3)
 ( Минуси  " ( 1  2 )  " ( 3  4 )) 
 ; Output: ((1 2) 3 4)

В appendпроцедурата добавя два (или повече) списъци един на друг. Тъй като Lisp списъци са свързани списъци, като положат два списъка има асимптотичната сложност време 

 ( Добавете  " ( 1  2 )  " ( 3  4 )) 
 ; Output: (1 2 3 4)
 ( Добавете  " ( 1  2  3 )  ' ()  ' ( а )  " ( 5  6 )) 
 ; Output: (1 2 3 5 6)

Споделено структура [ редактиране източник ][редактиране | редактиране на кода]

Lisp списъци, които са прости свързани списъци, могат да споделят структура с един друг. Така да се каже, два списъка могат да имат една и съща опашка , или крайната последователност на conses. Например, след изпълнението на следните общи Lisp код:

( Setf  Foo  ( списък  "с  " б  "в )) 
( setf  бар  ( минуси  " х  ( CDR  Foo )))

списъците fooи barса и съответно. Въпреки това, опашката е същата структура в двата списъка. Тя не е копие; минуси клетки, сочещи към и са на същите места на паметта за двата списъка.(a b c)(x b c)(b c)bc

Споделянето на структурата, а не копиране може да се получи драматично подобрение в производителността. Въпреки това, тази техника може да взаимодейства в нежелани начини с функции, които променят списъците, предадени им като аргументи. Промяна един списък, като например чрез замяна на cс goose, ще се отрази на другия:

 ( Setf  ( трета  Foo )  "гъска )

Това променя fooда , но по този начин също се променя , за да - един евентуално неочакван резултат. Това може да бъде източник на грешки, и функции, които променят техните аргументи са документирани като разрушителна поради тази причина.(a b goose)bar(x b goose)

Феновете на функционалното програмиране избягват деструктивни функции. В диалекта схема, която благоприятства функционален стил, имената на деструктивни функции с един поучителен удивителен знак, или "взрив" -such като са отбелязани set-car!(чете набор кола взрив ), който заменя на колата на един минуси. В общата Lisp диалект, деструктивни функции са често срещано явление; Еквивалентът на set-car!е кръстен rplacaза "замени кола." Тази функция е рядко се вижда обаче, както Общата Lisp включва специален механизъм, setfза да направи по-лесно да се определи и използва разрушителни функции. Честа стил в Общата Lisp е да се напише код функционално (без разрушителни повиквания), когато прототипи, а след това да се добави разрушителни разговори като оптимизация, където е безопасно да го направят.

Самостоятелно оценяване форми и цитира [ редактиране източник ][редактиране | редактиране на кода]

Lisp оценява изрази, които са въведени от потребителя. Символи и списъци оценяват до някаква друга (обикновено, по-прости) израз - например, символ оценява на стойността на имената на променливите него; оценява на . Въпреки това, повечето други форми оценяват, за да се: ако влизането в Lisp, той се връща .(+ 2 3)555

Всеки израз също могат да бъдат маркирани, за да го предпазите от оценен (колкото е необходимо за символи и списъци). Това е ролята на quoteспециален оператор, или неговото съкращение '(един кавички). Например, обикновено, ако влезе в символ foo, той се връща стойността на съответната променлива (или грешка, ако няма такава променлива). За да се позове на буквален символ, въведете или, обикновено, .(quote foo)'foo

И двете Общата Lisp и Схема също подкрепи backquote оператор (наречен quasiquote в схема), влязъл с `характер ( тежко ударение ). Това е почти същата като на обикновен цитат, освен това позволява изрази, за да бъдат оценени и техните стойности се определят чрез интерполация в списък котирана с запетая , цитата и запетаи АТ ,@ сплайс оператори. Ако променливата snueима стойност след това се изчисли на , докато Проверява . The backquote най-често се използва при определяне на макро разширения. (bar baz)`(foo ,snue)(foo (bar baz))`(foo ,@snue)(foo bar baz)

Самостоятелно оценяване форми и цитираните форми са еквивалентни на литерали Lisp е. То може да бъде възможно да се променят стойностите на (непостоянен) литерали в програмен код. Например, ако една функция връща цитиран форма, а кодът, който нарича функция променя формата, това може да промени поведението на функцията на последващи итерации.

( Defun  трябва-да-константа  () 
  " ( едно  две  три ))

( Нека  (( неща  ( трябва-да-постоянна ))) 
  ( setf  ( трета  неща )  "странен ))    ; лошо!

( Трябва-да-постоянна )    ; възвръщаемост (една две странни)

Модифицирането котирана форма като този обикновено се смята за лош стил, и се определя от ANSI Общата Lisp, както погрешно (в резултат на "неопределен" поведение в компилирани файлове, защото файл-компилатора може да се обединяват подобни константи, сложете ги в защита от запис на паметта, и т.н.).

Формализация на котиране Lisp е е било отбелязано от Дъглас Hofstadter (в Гьодел, Ешер, Бах ) и други като пример на философската идея за самостоятелно справка .

Обхват и затваряне [ редактиране източник ][редактиране | редактиране на кода]

В Lisp семейството се разделя върху използването на динамичен или статичен (известен още като лексикално) обхват . Clojure, Обща Lisp и схема да се възползва от статично определяне на обхвата по подразбиране, докато newLISP , Picolisp и вградените езици в Emacs и AutoCAD използват динамичен обхват на СЕП. Всъщност, Emacs използва едновременно динамичен и лексикално определяне на обхвата, тъй като версия 24.1.

Списък структура на програмен код; експлоатация от макроси и компилатори [ редактиране източник ][редактиране | редактиране на кода]

Фундаменталната разлика между Lisp и други езици е, че в Lisp, на текстово представяне на програма е просто четима за човека описание на същите вътрешни структури от данни (свързани списъци, символи, номера, знаци и т.н.), както ще бъде използван от базовия Lisp система.

Lisp използва това, за да изпълни един много мощен макро система. Подобно на други макро езици като C , макро връща код, който след това може да се компилира. Въпреки това, за разлика от C макроси, макросите са Lisp функции и така могат да се възползват от пълната мощ на Lisp.

Освен това, тъй като Lisp код има същата структура като списъци, макроси могат да бъдат изградени с някоя от функциите на списък за обработка на езика. С една дума, всичко, което Lisp може да направите, за да структура от данни, Lisp макроси могат да направят, за да код. За разлика от тях, в повечето други езици, изход парсера е чисто вътрешно за изпълнението на езика и не може да бъде манипулиран от програмист.

Тази функция го прави лесно да се разработят ефективни езици в рамките на езици. Например, общата Lisp система на обекта може да се прилага чисто като разширение на език, с помощта на макроси. Това означава, че ако молбата се нуждае от различен механизъм наследство, той може да използва различна система обект. Това е в рязък контраст с повечето други езици; например, Java не поддържа множествено наследяване и няма разумен начин да го добавите.

В опростени Lisp реализации, този списък структура е пряко тълкува , за да стартирате програмата; функция е буквално парче списък структура, която се пресича от преводача в нейното изпълнение. Въпреки това, повечето значителни Lisp системи включват и компилатор. Компилаторът превежда списък структура в машинен код или байткод за изпълнение. Този код може да работи толкова бързо, колкото код компилиран в конвенционалните езици като C.

Macros разширяват преди етапа на компилация, и по този начин се предлагат и някои интересни възможности. Ако дадена програма се нуждае от precomputed маса, след това макро може да създаде таблицата по време на компилация, така че компилатора трябва само изход на масата и не е необходимо да се обадите код, за да създадете таблицата по време на изпълнение. Някои Lisp реализации дори имат механизъм, eval-when, която позволява на код, за да присъства по време на компилация време (когато макро ще трябва да го), но не присъства в излъчваната модула.

Оценка и четене Оценка-печат контур [ редактиране източник ][редактиране | редактиране на кода]

Lisp езици често се използват с интерактивен команден ред , който може да бъде комбиниран с интегрирана среда за разработка (IDE). Видовете потребителски в изрази в командния ред, или насочва IDE да ги предават на Lisp система. Lisp чете въведените изрази, оценява ги, и отпечатва резултата. Поради тази причина, на Lisp командния ред се нарича четене Оценка-печат контур ( REPL ).

Основното действие на REPL е както следва. Това е опростено описание, което пропуска много елементи от истинско Lisp, като цитира и макроси.

The readфункцията приема текстови S-изрази като вход, и ги прави разбор на вътрешната структура на данните. Например, ако сте написали текста в командния ред, се превежда това в свързан списък с три елемента: символа , номер 1 и номер 2. Стана така, че този списък е също валидно парче Lisp код; това означава, че може да се оцени. Това е така, защото колата на имената на списък функция-действието на допълнение.(+ 1 2)read+

Имайте предвид, че fooще се чете като един символ. 123ще се чете като броят сто двадесет и три. "123"ще се чете като низа "123".

На evalфункцията оценява данните, връщайки нула или повече други Lisp данни като резултат. Оценка не трябва да означава интерпретация; някои Lisp системи съставят всеки израз на родния код машина. Тя е проста, обаче, за да се опише оценка като интерпретация: За да се оцени списък чиято кола имена функция, evalпърво оценява всеки от аргументите, дадени в своята CDR, след това се прилага функцията на аргументите. В този случай, функцията е допълнение, и го прилага към списъка за аргумент се получава отговорът . Това е резултат от оценката.(1 2)3

Символът fooоценява на стойност на Mt. символа. Данни като низа "123" се изчислява на същата струна. Списъкът оценява към списъка (1 2 3).(quote (1 2 3))

Това е работа на printфункцията да представлява изход за потребителя. За обикновен резултат като 3това е тривиално. Израз, който се оценява, като част от списък структура би изисквало, че printпреминават в списъка и да го отпечатате като S-израз.

За изпълнение на Lisp REPL, е необходимо само да прилагат тези три функции и функция безкраен цикъл. (Разбира се, прилагането на evalще бъде сложен, тъй като тя трябва също да приложи всички специални оператори като ifили lambda.) Това прави, основен REPL е един ред код: .(loop (print (eval (read))))

В Lisp REPL обикновено също осигурява вход за редактиране, за историята на въвеждане, обработка на грешки и интерфейс към дебъгер.

Lisp обикновено се оценяват с нетърпение . В Общата Lisp , аргументите са оценени в приложната цел ( "най-лявата-вътрешния '), докато в Схема цел на аргументи е неопределена, оставяйки място за оптимизация от компилатор.

Контролни структури [ редактиране източник ][редактиране | редактиране на кода]

Lisp първоначално имаше много малко контролни структури, но много повече по време на еволюцията на езика са били добавени. (Оригинал условен оператор Lisp е, cond, е предшественик на по-късни if-then-elseструктури.)

Програмистите в диалекта Схема често изразяват вериги, използващи опашка рекурсия . Сходство Схема в учебната компютърни науки е довело някои ученици да вярват, че опашката рекурсия е единственият, или най-често срещаните, начина, по който да се напише повторения в Lisp, но това е неправилно. Всички често наблюдавани Lisp диалекти имат наложително стил итерация конструкции, от схема на doлиния за Общата Lisp сложни лидер loopизрази. Освен това, основният въпрос, който прави този обективен, а не субективен въпрос е, че Схемата прави специфични изисквания за обработка на опашката разговори , и по този начин поради причината, че използването на опашката рекурсия обикновено се насърчава за схема е, че практиката е изрично подкрепено от определението на език. За разлика от това, ANSI Общата Lisp не изисква  оптимизацията често нарича елиминиране опашка повикване. По този начин, на факта, че опашката рекурсивни стил като случайни заместител на използването на по-традиционните итерация конструкции (като например dodolistили loop) не е препоръчително  в Общата Lisp не е само въпрос на стилистични предпочитания, но потенциално една от ефективност (от видима опашка повикване в Общата Lisp не могат да се съберат като обикновен скок ) и програма за коректност (тъй като опашката рекурсия може да се увеличи използването стак в Общата Lisp, рискувайки стека преливане ).

Някои Lisp структури за контрол са специални оператори , еквивалентни на синтактичните ключови думи и други езици. Изразяване използват тези оператори имат същия външен вид като функция повиквания, но се различават по това, че аргументите, не е задължително да се оценяват, или, в случая на експресия на повторение, може да бъде оценена на повече от веднъж.

За разлика от повечето други основни езици за програмиране, Lisp позволява прилагането на контролните структури, използващи езика. Няколко контролни структури са реализирани като Lisp макроси, и дори може да бъде макро-разширена от програмист, който иска да знае как те работят.

И двете Общата Lisp и схема има оператори за не-локален контрол на потока. Различията в тези оператори са едни от най-дълбоките различия между двете диалекти. Схема поддържа входящ продължения с помощта на call/ccпроцедурата, която позволява на програмата да се спаси (и по-късно възстановяване) на определено място в изпълнение. Общата Lisp не поддържа входящ продължения, но не поддържа няколко начина за манипулиране евакуация продължения.

Често същия алгоритъм може да се изрази в Lisp и в двата императив или функционален стил. Както беше отбелязано по-горе, Схема благоприятства функционалното стил, с помощта на опашката рекурсия и продължения, за да изразят контрол на потока. Въпреки това, наложително стил все още е напълно възможно. Стилът предпочитан от много Общата Lisp програмисти може да изглежда по-добре запознати с програмисти използват за структурирани езици като C, докато този предпочитан от интриганти по-голяма степен прилича на чист-функционални езици като Haskell .

Поради ранното наследство Lisp в преработка списък, той разполага с широка гама от функции, по-висок ред, свързани с повторение над последователности. В много случаи ще бъде необходимо изрично линия на други езици (като forконтур на С) в Lisp същата задача може да се осъществи с функция за по-висок порядък. (Същото се отнася и за много функционални програмни езици.)

Един добър пример за това е функция, която в схема се нарича mapи в Общата Lisp се нарича mapcar. Получавайки функция и един или повече списъци, mapcarсе прилага функцията последователно с елементи на списъци "с цел, събиране на резултатите в нов списък:

 ( Mapcar  # " +  " ( 1  2  3  4  5 )  " ( 10  20  30  40  50 ))
Това се отнася за +функцията на всяка съответстваща двойка списък елементи, при което се получава резултата .(11 22 33 44 55)