Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
376 lines (330 sloc) 44.3 KB
\chapter{Введение: почему Lisp?}
\label{ch:01}
\thispagestyle{empty}
Если вы считаете, что наибольшее удовольствие в программировании приносит напи\-са\-ние
лаконичных и выразительных программ, просто и прозрачно выражающих ваши мысли, тогда
программирование на Common Lisp будет самым приятным из того, что вы можете делать на
компьютере. Используя Common Lisp, вы будете успевать больше и быстрее, чем с
практически любым другим языком.
Серьёзное заявление. Могу ли я доказать это? Да, но не на нескольких страницах
введения. Вам придётся познакомиться с Lisp поближе и убедиться в этом самим, так что
всё-таки придётся прочитать книгу до конца. Сначала я опишу свой путь к языку Lisp, а в
следующей главе я объясню выгоды, которые вы получите от его изучения.
Я~-- один из немногих Lisp-хакеров во втором поколении. Мой отец начал заниматься
компьютерами с написания на ассемблере операционной системы для машины, которую он
использовал для сбора данных при подготовке своей докторской диссертации по физике. После
работы с компьютерами в разных физических лабораториях, к 80-м, отец полностью оставил
физику и стал работать в большой фармацевтической компании.
У этой компании был проект по созданию программы, моделирующей производственные процессы
на химических заводах. Старая команда писала всё на языке FORTRAN, использовала половину бюджета и
почти всё отведённое время, но не смогла продемонстрировать никаких результатов. Это было в
80-х, на пике развития искусственного интеллекта (ИИ), и Lisp так и витал в воздухе. Так что
мой отец~-- в то время ещё не поклонник Lisp~-- пошёл в университет Карнеги-Меллона,
чтобы пообщаться с людьми, работавшими над тем, что впоследствии стало языком Common Lisp, и
узнать, сможет ли Lisp подойти для его проекта.
Ребята из университета показали ему кое-что из своих разработок, и это его убедило. Отец,
в свою очередь, убедил своих боссов позволить ему взять провальный проект и переделать его на
Lisp. Год спустя, используя остатки бюджета, команда отца представила работающее
приложение, обладающее возможностями, на реализацию которых старая команда уже и не
надеялась. Мой папа считает, что причина успеха~-- в решении использовать Lisp.
Однако это всего лишь первый эпизод. Может быть, мой отец ошибался в причине своего
успеха. Или, может быть, Lisp был лучше других языков лишь для того времени. В~настоящее
время мы имеем кучу новых языков программирования, многие из которых переняли часть
достоинств Lisp. Правда ли, что использование языка Lisp может дать вам те же выгоды,
что и моему отцу в 80-х? Читайте дальше.
Несмотря на все усилия отца, я не изучал Lisp в университете. После учёбы, которая
не содержала много программирования на каком-либо языке, я увлёкся Web и вернулся к
компьютерам. Сначала я писал на Perl, изучив его достаточно, чтобы создать форум для сайта
журнала Mother Jones, после этого я работал над большими (по тем временам) сайтами,
такими как, например, сайт компании Nike, запущенный к олимпийским играм 1996 года. После
этого я перешёл на Java, будучи одним из первых разработчиков в WebLogic (теперь эта
компания~-- часть BEA). После WebLogic я участвовал в другом стартапе, где был ведущим
программистом по построению транзакционной системы обмена сообщениями на Java. Со временем
я освоил как популярные языки~-- C, C++ и Python, так и менее известные: Smalltalk, Eiffel и Beta.
Итак, я знал два языка вдоль и поперёк и был поверхностно знаком с несколькими другими.
В~конечном счёте я понял, что источником моего интереса к языкам программирования
была идея, заложенная рассказами отца о Lisp,~-- идея, что разные языки
программирования существенно различаются, и, несмотря на формальное равенство всех языков
по Тьюрингу, вы действительно можете быть гораздо продуктивнее, используя
одни языки вместо других, и получать при этом больше удовольствия. Поэтому я начал учить
Lisp в свободное время. Меня воодушевляло то, насколько быстро я проходил путь от идеи к
работающему коду.
Например, в одном из отпусков, имея около недели свободного времени, я решил написать
на Lisp программу для игры в Го с использованием генетических алгоритмов, так как писал её
до этого на Java. Даже с моими зачаточными знаниями Common Lisp (приходилось искать
самые базовые функции) я работал более продуктивно, чем если бы я писал это на Java,
несмотря на несколько лет работы с ней.
Похожий эксперимент привёл к созданию библиотеки, о которой я расскажу в главе~\ref{ch:24}. В
начале моей карьеры в WebLogic я написал библиотеку на Java для анализа class-файлов.
Она работала, но код был запутан, и его трудно было изменить или добавить новую функциональность.
В~течение нескольких лет я пытался переписать библиотеку,
думая, что смогу использовать мои новые знания в Java и не увязнуть в куче дублирующегося
кода, но так и не смог. Когда же я попробовал переписать её на Common Lisp, это заняло всего
2 дня, и я получил не просто библиотеку для разбора class-файлов Java, но библиотеку для
разбора любых двоичных файлов. Вы увидите, как она работает, в главе~\ref{ch:24} и воспользуетесь
ею в главе~\ref{ch:25} для разбора тегов ID3 в MP3-файлах.
\section{Почему Lisp?}
Сложно объяснить на нескольких страницах введения, почему пользователи языка любят
какой-то конкретный язык, ещё сложнее объяснить, почему вы должны тратить своё время на
его изучение. Личный пример не слишком убеждает. Может быть, я люблю Lisp из-за какой-то
мозговой аномалии. Это может быть даже генетическим отклонением, так
как у моего отца эта аномалия, похоже, тоже была. Так что прежде, чем вы погрузитесь в изучение языка
Lisp, вполне естественно желание узнать, что это вам даст, какую выгоду
принесёт.
Для некоторых языков выгода очевидна. Например, если вы хотите писать низкоуровневые
программы для Unix, то должны выучить C. А если вы хотите писать кросс-платформенные
приложения, то должны использовать Java. А многие компании до сих пор используют
C++, так что если вы хотите получить работу в одной из них, то должны знать C++.
Тем не менее для большинства языков выгоду не так просто выделить. Мы имеем дело с
субъективными оценками того, насколько язык удобно использовать. Защитники Perl любят
говорить, что он <<делает простые вещи простыми, а сложные~-- возможными>>, и радуются факту,
озвученному в девизе Perl~-- <<Есть более чем один способ сделать это>>\pclfootnote{Perl
также заслуживает изучения в качестве <<изоленты для Internet>>.}. С другой стороны,
фанаты языка Python думают, что Python~-- прозрачный и простой язык, и код на Python проще
понять, потому что, как гласит их лозунг, <<Есть лишь один способ сделать это>>.
Так почему же Common Lisp? Здесь нет такой очевидной выгоды, как для C, Java или C++
(конечно, если вы не являетесь счастливым обладателем Lisp-машины). Выгоды от использования
Lisp заключены скорее в опыте и ощущениях от его использования. В~остальной части книги
я буду показывать отличительные черты языка и учить вас ими пользоваться, а вы сможете
по себе оценить, каково это. Для начала я попытаюсь дать вам введение в философию Lisp.
В~качестве девиза для Common Lisp лучше всего подходит похожее на дзен-коан описание
<<программируемый язык программирования>>. Хотя данный девиз выглядит несколько запутанно,
он тем не менее выделяет суть преимущества, которое Lisp до сих пор имеет перед другими
языками программирования. Более, чем другие языки, Common Lisp следует философии: что
хорошо для разработчика языка, то хорошо для его пользователей. Программируя на Common
Lisp, вы, скорее всего, никогда не обнаружите нехватки каких-то возможностей в языке,
которые упростили бы программирование, потому что, как будет показано далее, вы можете
просто добавить эти возможности в язык.
Следовательно, в программах на Common Lisp обычно очень ярко проявляется соответствие
между вашим представлением о том, как программа должна работать, и кодом, который вы
пишете. Ваши идеи не замутняются нагромождением скучного кода и бесконечно повторяющимися
типичными приёмами. Это упрощает поддержку кода, потому что вам больше не приходится
бродить по нему всякий раз, когда вы хотите внести какие-то изменения. Даже
систематические изменения в программе могут быть достигнуты относительно малыми
изменениями исходного кода. Это также означает, что вы будете писать код быстрее; вы
будете писать меньше кода и не будете терять времени на поиск способа красиво выразить свои идеи
вопреки ограничениям, накладываемым языком программирования\pclfootnote{К сожалению, нет
достоверных исследований продуктивности для разных языков программирования. Один из
отчётов, показывающих, что Lisp не уступает C++ и Java в совокупной эффективности
программ и труда программистов, находится по адресу
\url{http://www.norvig.com/java-lisp.html}.}.
Common Lisp~-- это также прекрасный язык для программирования методом проб и ошибок:
если в начале работы над программой вы ещё не знаете точно, как она будет устроена, то
Common Lisp предоставляет ряд возможностей для инкрементальной и интерактивной разработки.
Интерактивный цикл read-eval-print, о котором я расскажу в следующей главе, позволяет
непрерывно взаимодействовать с вашей программой по мере её разработки. Пишете новую
функцию. Тестируете её. Изменяете её. Пробуете другие подходы. Вам не
приходится долго ждать компиляции\pclfootnote{Психологи выделяют состояние
сознания, называемое потоком (flow), в котором мы обладаем немыслимой концентрацией и
производительностью~(описан в книге Михая Чиксентмихайи (Mihaly Csikszentmihalyi)~<<Поток.
Психология оптимального переживания>>). Важность данного состояния при программировании
была осознана в последние два десятилетия, с тех пор как данная тема была освещена в
классической книге о человеческом факторе в программировании <<Эффективные проекты и
команды>> Тома Демарко (Tom DeMarko) и Тимоти Листера (Tim Lister). Два ключевых факта о
состоянии потока: требуется около 15 минут, чтобы войти в него, и даже короткие
прерывания могут вывести из данного состояния; после этого на вход в него снова потребуется
15 минут. Демарко и Листер, как и многие последующие авторы, концентрируются на
избавлении от прерываний, разрушающих состояние потока, таких как телефонные звонки и
неподходящие визиты начальника. Но незаслуженно мало внимания уделяется не менее важному фактору~--
прерываниям из-за инструментов, которые мы используем в своей работе. Например, языки,
требующие долгой компиляции, перед тем как можно будет запустить код, могут быть
не менее губительными для потока, чем надоедливый начальник или звонки по телефону. Lisp
может рассматриваться как язык, спроектированный для программирования в состоянии потока.}.
Ещё две особенности, способствующие непрерывному и интерактивному стилю программирования,
динамическая типизация и система обработки условий. Первое позволяет вам тратить меньше
времени на убеждение компилятора разрешить вам запустить программу и больше времени на её
действительный запуск и работу с ней\pclfootnote{Эта точка зрения противоречит некоторым
распространённым мнениям. Статическая типизация против динамической~-- одна из
классических тем для словесных перепалок между программистами. Если вы пришли из мира
С++ или Java (или из мира функциональных языков со статической типизацией, таких как ML
или Haskell) и не представляете жизни без статических проверок типов, можете закрыть эту
книгу. Но прежде чем сделаете это, вам, возможно, будет интересно узнать, что пишут о
динамической типизации такие её поборники, как Мартин Фаулер и Брюс Эккель, в своих
блогах~-- \mbox{\url{http://www.artima.com/weblogs/viewpost.jsp?thread=4639}} и
\mbox{\url{http://www.mindview.net/WebLog/log-0025}}. С другой стороны, люди из мира
SmallTalk, Python, Perl или Ruby будут чувствовать себя как дома при использовании этого
аспекта Common Lisp.}. Второе позволяет интерактивно разрабатывать даже код обработки
ошибок.
Ещё одно следствие <<программируемости>> Lisp~-- это то, что, кроме
возможности вносить мелкие изменения в язык, упрощающие написание программ,
есть возможность без труда отражать в языке значительные новые понятия, касающиеся общего
устройства языка программирования. Например, первоначальная реализация Common Lisp Object
System (CLOS)~-- объектной системы Common Lisp~-- была библиотекой, написанной на самом
Common Lisp. Это позволило Lisp-программистам получить реаль\-ный опыт работы с
возможностями, которые она предоставляла, ещё до того, как библиотека была
официально включена в состав языка.
Какая бы новая парадигма программирования ни появилась, Common Lisp, скорее всего, без
труда сможет впитать её без изменений в ядре языка. Например, один программист на Lisp
недавно написал библиотеку AspectL, которая добавляет к Common Lisp поддержку
аспектно-ориентированного программирования (AOP)\pclfootnote{AspectL~-- интересный проект,
так как его предшественника из мира Java, AspectJ, создал Грегор Кичалес (Gregor
Kiczales), один из проектировщиков объектной и метаобъектной системы Common Lisp. Для
многих Lisp-программистов AspectJ выглядел как попытка автора портировать идеи Lisp в
Java. Тем не менее Паскаль Констанца (Pascal Costanza)~-- автор AspectL~-- считает, что
в AOP есть интересные идеи, которые будут полезны в Common Lisp. Конечно, он смог
реа\-ли\-зо\-вать AspectL в виде библиотеки благодаря немыслимой гибкости Common Lisp Meta
Object Protocol, разработанного Кичалесом. Для реализации AspectJ пришлось написать
отдельный компилятор для компиляции нового языка в Java-код. Страница проекта AspectL
находится по адресу \url{http://common-lisp.net/project/aspectl/}.}. Если будущее за
AOP, то Common Lisp сможет поддерживать его без изменений в базовом языке и без
дополнительных препроцессоров и прекомпиляторов\pclfootnote{Или, выражаясь более технически
грамотно, Common Lisp сам предоставляет возможность интеграции компиляторов
для встроенных языков.}.
\section{С чего всё началось}
Common Lisp~-- современный потомок языка программирования Lisp, придуманного Джоном
Маккарти (John McCarthy) в 1956 году. Lisp был создан для <<обработки символьных
данных>>\pclfootnote{Lisp 1.5 Programmer's Manual (M. I. T. Press, 1962).} и получил своё имя от
одной вещи, в которой он был очень хорош: обработки списков (LISt Processing). Много воды
утекло с тех пор, и теперь Common Lisp обогащён набором всех современных типов данных, которые
вам только могут понадобиться, а также системой обработки условий, которая, как вы
увидите в главе~\ref{ch:19}, предоставляет целый дополнительный уровень гибкости, отсутствующий в системах обработки
исключений таких языков, как C++, Java, Python; мощной системой объектно-ориентированного
программирования; несколькими особенностями, которых нет ни в одном другом языке. Как
такое возможно? Что, вы спросите, обусловило превращение Lisp в такой богатый язык?
Что же, Маккарти был (и остаётся\translationnote{Джон Маккарти умер 24 октября 2011 г.})
исследователем в области искусственного интеллекта, и многие
особенности, заложенные им в первую версию Lisp, сделали этот язык замечательным
инструментом для программирования задач искусственного интеллекта. Во время бума ИИ в 80-е Lisp
оставался излюбленным языком для решения сложных задач, как то: автоматическое
доказательство теорем, планирование и составление расписаний, компьютерное зрение. Это
были задачи, решение которых требовало написания сложных программ, для чего нужен был мощный язык,
так что программисты ИИ сделали Lisp таковым. Помогла и <<холодная война>>, так как Пентагон
выделял деньги Управлению перспективных исследовательских программ (DARPA), и часть этих
денег попадала к людям, занимающимся моделированием крупных сражений, автоматическим
планированием и интерфейсами на естественных языках. Эти люди также использовали Lisp и
продолжали совершенствовать его, чтобы язык полностью удовлетворял их потребностям.
Те же силы, что развивали Lisp, также расширяли границы и в других направлениях~--
сложные проблемы ИИ требуют больших вычислительных ресурсов, как бы вы их ни решали, и
если вы примените закон Мура в обратную сторону, то сможете себе представить, сколь
скудными эти ресурсы были в 80-е. Так что разработчики должны были найти все возможные
пути улучшения производительности своих реализаций языка. В~результате этих усилий
современные реализации Common Lisp часто включают в себя сложные компиляторы, переводящие
программы в язык,
понятный машине. Хотя сегодня благодаря закону Мура можно получить высокую
производительность даже от интерпретируемых языков, это больше не представляет проблемы для
Common Lisp. И, как я покажу в главе~\ref{ch:32}, используя специальные (необязательные)
объявления, с помощью хорошего компилятора можно получить вполне приличный машинный код,
сравнимый с тем, который выдаст компилятор~C.
\textintable{Но я изучал Lisp раньше, и это было не так, как вы описываете!}{Если вы
изучали Lisp в прошлом, то возможно ваше представление о нём не имеет ничего общего с
Common Lisp. Хотя Common Lisp вытеснил большинство диалектов, от которых он был
порождён, это не единственный сохранившийся диалект, и в зависимости от того, где и
когда вы встретились с Lisp, вы могли хорошо изучить один из этих, отличных от Common
Lisp, диалектов.
Кроме Common Lisp, активное сообщество пользователей есть у диалекта Lisp общего
назначения под названием Scheme. Common Lisp позаимствовал из Scheme несколько важных
особенностей, но никогда не пытался заменить его.
Язык Scheme, разработанный в Массачусетском технологическом институте (MIT), был быстро
принят в качестве языка для обучения программированию на младших курсах университетов.
Scheme изначально занимал отдельную нишу, в частности проектировщики языка постарались
сохранить ядро Scheme настолько малым и прос\-тым, насколько это возможно. Это давало
очевидные выгоды при использовании Scheme как языка для обучения, а также для
исследователей в области языков программирования, которым важна возможность формального
доказательства утверждений о языке.
Было также ещё одно преимущество: язык легко можно было изучить по
спецификации. Все эти преимущества достигнуты за счёт отсутствия многих удобных
особенностей, стандартизованных в Common Lisp. Конкретные реализации Scheme могут
предоставлять эти возможности, но такие отклонения от стандарта делают написание
переносимого кода на Scheme более сложным, чем на Common Lisp.
В~Scheme гораздо большее внимание, чем в Common Lisp, уделяется функциональному стилю
программирования и использованию рекурсии. Если вы изучали Lisp в университете и остались
под впечатлением, что это академический язык, не подходящий для применения в реальной жизни,
вероятно, что вы изучали именно Scheme. Не то, чтобы это было справедливым утверждением о Scheme,
но под это определение ещё меньше подходит Common Lisp, создававшийся для реальных
инженерных задач, а не для теоретических исследований.
Также, если вы изучали Scheme, вас могут сбить с толку некоторые различия между Scheme и
Common Lisp. Эти различия являются поводом непрекращающихся религиозных войн между
горячими поклонниками этих диалектов. В~данной книге я постараюсь указать
на наиболее существенные различия.
Два других распространённых диалекта Lisp~-- Elisp, язык расширений для
редактора Emacs, и Autolisp, язык расширений для программы Autodesk AutoCAD. Хотя,
возможно, суммарный объём кода, написанного на этих диалектах, превосходит весь остальной
код на Lisp вместе взятый, оба их диалекта могут использоваться только в рамках приложений,
которые они расширяют. Кроме того, они являются устаревшими, по сравнению и с Common Lisp, и
с Scheme. Если вы использовали один из этих диалектов, приготовьтесь к путешествию на
Lisp-машине времени на несколько десятилетий вперёд.}
80-е~-- это также эра Lisp-машин. Несколько компаний, самая известная из которых
Symbolics, выпускали компьютеры, которые могли запускать Lisp-код непосредственно на своих
чипах. Так Lisp стал языком системного программирования, который использовали для
написания операционных систем, текстовых редакторов, компиляторов и практически всего
остального программного обеспечения Lisp-ма\-шин.
Фактически к началу 80-х существовало множество Lisp-ла\-бо\-ра\-то\-рий и несколько компаний,
каждая со своей реализацией Lisp, их было так много, что люди из DARPA стали высказывать
свои опасения о разобщённости Lisp-со\-об\-щест\-ва. Чтобы достигнуть единства, группа
Lisp-ха\-ке\-ров собралась вместе и начала процесс стандартизации нового языка, Common Lisp,
который бы впитал в себя лучшие черты существующих диалектов. Их работа запечатлена в
книге Common Lisp the Language (CLtL) Гая Стила (Guy Steele, Digital Press, 1984).
К 1986 году существовало несколько реализаций стандарта, призванного заменить разобщённые
диалекты. В~1996-м организация The American National Standards Institute (ANSI) выпустила
стандарт, расширяющий Common Lisp на базе CLtL, добавив в него новую функциональность,
такую как CLOS и систему обработки условий. Но и это не было последним словом: как CLtL
до этого, так и стандарт ANSI теперь намеренно позволяет разработчикам реализаций
экспериментировать с тем, как лучше сделать те или иные вещи: реализация Lisp содержит
богатую среду исполнения с доступом к графическому пользовательскому интерфейсу,
многопоточности, сокетам TCP/IP и многому другому. В~наши дни Common Lisp эволюционирует,
как и большинство других языков с открытым кодом: пользователи языка пишут
библиотеки, которые им необходимы, и часто делают их доступными для всего сообщества. В
последние годы, в частности, заметно усиление активности в разработке Lisp-би\-бли\-о\-тек
с открытым кодом.
Так что, с одной стороны, Lisp~-- один из классических языков информатики (Computer
Science), основанный на проверенных временем идеях\pclfootnote{Вот некоторые идеи, впервые
реализованные в Lisp: конструкция \lstinline{if-then-else}, рекурсивный вызов функций, динамическое
распределение памяти, сборка мусора, представление функций как полноценных объектов,
лексические замыкания, интерактивное программирование, инкрементальная компиляция и
динамическая типизация.}. С другой стороны, Lisp~-- современный язык общего назначения,
с дизайном, отражающим практический подход к решению сложных задач с максимальной
надёжностью и эффективностью. Единственным недостатком <<классического>> наследия Lisp
является то, что многие всё ещё топчутся вокруг представлений о Lisp, основанных на
определённом диалекте этого языка, который они открыли для себя в середине прошлого
столетия, в то время когда Маккарти разработал Lisp. Если кто-то говорит вам, что Lisp~--
только интерпретируемый язык, что он медленный или что вы обязаны использовать рекурсию
буквально для всего, спросите вашего оппонента, какой диалект Lisp'а имеется в видy и
носили ли люди брюки-клёш, когда он изучал Lisp\pclfootnote{Один из наиболее распространённых мифов
о Lisp гласит, что он мёртв. Хотя Common Lisp действительно используется не так
широко, как, скажем, Visual Basic или Java, странно называть мёртвым язык, который
постоянно приобретает новых пользователей и используется для разработки новых
проектов. Несколько последних случаев успешного применения Lisp~-- проект Viaweb Пола
Грэхема, впоследствии купленный Yahoo и получивший название Yahoo Store; система
заказа авиабилетов ITA Software\translationnote{купленная компанией Google 1 июля 2010г.};
QPX, используемый компанией Orbitz и другими для
продажи билетов он-лайн; игра <<Jak and Daxter>> компании Naughty Dog для PlayStation 2,
значительная часть которой написана на специализированном диалекте Lisp GOAL, компилятор которого, в свою
очередь, написан на Common Lisp; Roomba~-- автоматический робот-пылесос, программная
начинка которого написана на~L~-- подмножестве Common Lisp. Возможно, ещё более убедительны
рост объёма и популярности сайта \url{http://common-lisp.net}, на котором
размещаются проекты на Common Lisp с открытым кодом, и стремительно возросшее в
последние годы число локальных групп пользователей Lisp.}.
\section{Для кого эта книга?}
Эта книга для вас, если вы интересуетесь Common Lisp, независимо от
того, уверены ли вы в своём желании его использовать или просто хотите понять,
из-за чего вокруг него разгорелась вся эта шумиха.
Если вы уже изучали Lisp, но не смогли перейти от академических упражнений к созданию
реальных полезных программ, данная книга поможет вам сделать это. С~другой
стороны, необязательно испытывать желание применять Lisp, чтобы получить пользу от этой
книги.
Если вы упёртый прагматик, желающий знать достоинства Common Lisp перед другими языками,
такими как Perl, Python, Java, C или C\#, эта книга даст вам пищу для размышлений.
Или, может быть, вам нет никакого дела до использования Lisp и вы уверены, что он
ничуть не лучше языков, которые вы уже знаете, но вам надоели заявления какого-нибудь
Lisp-программиста, что вы просто <<не в теме>>. Если так, то в данной книге вы
найдёте краткое введение в Common Lisp. Если после чтения этой книги вы по-прежнему будете
думать, что Common Lisp ничем не лучше, чем ваши любимые языки, у вас будут веские
обоснованные аргументы.
В~книге описываются не только синтаксис и семантика языка, но и подходы к напи\-са\-нию на
нём полезных программ. В~первой части книги я описываю сам язык и даю несколько
практических примеров. После описания большей части языка (включая несколько областей,
оставленных в других книгах на самостоятельное изучение) следует девять практических глав,
в которых я помогу вам написать несколько полезных программ среднего размера: спам-фильтр,
разборщик двоичных файлов, каталог MP3, вещание MP3 по сети и веб-интерфейс к каталогу MP3 на
сервере.
По окончании чтения книги вы будете знакомы с большинством основных возможностей языка
и с тем, как их следует использовать. Вы приобретёте опыт использования Common Lisp для
написания нетривиальных программ и будете готовы к дальнейшему самостоятельному изучению
языка. И хотя у каждого свой путь к Lisp, я надеюсь, данная книга поможет вам на этом
пути. Итак, приступим!
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "pcl-ru"
%%% TeX-open-quote: "<<"
%%% TeX-close-quote: ">>"
%%% End: