LISP
В Лиспе, если охота аспектно-ориентированного программирования, нужно лишь настругать немного макрокоманд, и готово. В Java, нужен Грегор Кичалес, создающий новую фирму, и месяцы и годы попыток заставить всё работать.
(defterm LISP («язык программирования» (состоящий (из (смайликов (чуть (более (чем (целиком)))))))))
(defstatement Считается, что [2] LISP (означает ‘(LISt Processor — обработчик списков.)))
(defquote ‘(Ибо воистину. Первый Язык, жемчужина посреди простых камней, и нет языков кроме Него. Скобки, в которых пустота — тело Его, мистическое двуединство кода и данных — дух Его, божественная рекурсия — сердце Его. Истинно говорю вам, избегающий света Его есть безумец, вот, свершается кара над главой его, и убогостью отмечены поделия его, подобные пустым глиняным горшкам рядом с хрустальным сосудом благодати Его. Принявший же и постигший истинный свет Его подобен прямой и отточенной стреле, чисты помыслы его и крепка рука его, и благословенны творения его, дарующие радость и утоляющие печали, ибо одухотворены духом Его и отмечены благодатью Его.)
Пример простой программы на LISP
- 1 (defsection «история-создания»
- 2 (defsection кошерность
- 3 (defsection галерея
- 3.1 Гоатсе!
- 4.1 (defsubsection статьи
- 4.2 (defsubsection примечания
(defsection «история-создания»
- «Перволисп был открыт Джоном Маккарти (R.I.P.), реализовавшем процедуру eval для инструкций, записанных в списки вместе с данными, что позволило объединить данные и код в единый тип S-expression (symbolic expression) и отказаться от отдельного M-expression (meta expression) для инструкций, имевшего другой синтаксис.»
- «Emacs Lisp разработан Ричардом Столлманом для редактора GNU Emacs. Является самым старым лиспом из остающихся в ходу.»
- «ANSI Common Lisp (стандарт ANSI X3.226-1994) был разработан, чтобы объединить воедино в одном стандарте разнообразные лиспы (Interlisp, LML и пр.), является наиболее практичным диалектом, на котором пишут вебсерверы, вебсайты и вебдваноль.»
- «Scheme создали Гай Стил [3] и Джеральд Сассман в качестве учебного языка для демонстрации колдовских возможностей машины и написания книги SICP. В процессе работы над языком они достигли такой глубины сатори, что сочиняли до десятка разных интерпретаторов в неделю.»)
- «Инженеры из Apple Computer, не останавливаясь на достигнутом (Object Pascal), создали Dylan, совмещающий синтаксис Паскаля с возможностями Lisp, но всем было похуй. А потом вернулся Джобс, и в Apple воцарился Objective C, совмещающий типобезопасность C со скоростью SmallTalk.»
(defsection кошерность
- «функциональная основа (хотя на самом деле лисп — язык мультипарадигменный)»
- «прямой доступ к AST — на лиспе очень легко метапрограммировать. За это его любит, например, Луговский, Лейн»
- «истинные макрокоманды, а не всякое препроцессорное говно»
- «интерпретатор Лиспа, написанный на Лиспе, занимает 15 строк, который еще раз показывает, что лисп — это вам не хухры-мухры[4] »
- «возможность отлаживать, модифицировать, обновлять работающую программу, не перезагружая ее»
- «мощный рантайм» [5]
- «эффективные кроссплатформенные реализации»
- «уважается Луговским — nuff said.»))
(defsection галерея
Гоатсе!
(((L I S P )( L I S P ) ( L I S P ) ( L I S P ))) * ( ) * B( ) ) ) B e( `. ) ) : e a` ) ) ) ) a t ) ) ) \ —__ \ : t i ) _—~~ ~—__) ) i n _-~ ~-_ ) n g _ _.———.______) ) g ______(( _ ___ _ (_(__H ) t . S ___) ______ (_(____t ) ) t h ( ) I ____)) APPLY (_____D )_) h e ( () C_____) EVAL ) (___P ) e ( ( _P_____)______) )) _) ) a ( )__ \_________)) (__) ) a v ( ____) `—- —‘ ) v e ( _ ___ )_ _) ) e r ( ) ( ) ) r a ( ) ( λ ) ) a g ( ) ) ( ) )g e ( ) ) (__)(___) ) )e s ( ) ( ) ) )s * ( ) ( ) ) )* (((L I S P )( L I S P ) ( L I S P ) ( L I S P )))
(defsection «см. также»
(defsubsection статьи
(defsubsection примечания
- ↑ (Т.н. „Десятое правило Гринспена“ (первых девяти не существует))
- ↑ (Есть мнение, что на самом деле LISP означает Lots of Irritating Superfluous Parentheses, хотя некоторые говорят что на самом деле это Lost in a Sea of Parentheses. Существует также трактовка Lots of Incomprehensible Statements with Parenthesis
- ↑ (Впоследствии соавтор Явы
- ↑ ни асилил на RSDN [1]
- ↑ (let ((x ‘(a b))) (setf (cdr x) x))
Источник: neolurk.org
Язык LISP для студентов и инженеров. Первая программа
Язык программирования Lisp: функции, синтаксис, среда разработки
Более сорока лет назад разработан и внедрен в использование для выполнения целей искусственного интеллекта язык программирования LISP (ЛИСП), позднее ставший популярным среди пользователей ПО AutoCAD. Он создан для символьных вычислений. С течением времени был преобразован, чтобы соответствовать новым потребностям ИИ.
Начинающим пользователям, изучающим его архитектуру, рекомендуется рассматривать его в качестве формальной знаковой системы.
Это imperative language (императивный), действия которого описывают выполнение алгоритма, отличается от других, декларативных, предполагающих определение ограничений и соотношений в предметной сфере поставленной цели. По сравнению с другими подобными разработками С++ и FORTRAN, ЛИСП наделен большей функциональностью. Его популярность обусловлена большими возможностями для программирования в сочетании с мощным набором:
Это средства построения данных структур обозначения высокого уровня.
Конструкция
LISP синтаксис и семантика, разработанные программистами, обусловлены теорией рекурсивных функций. Символьные, s-выражения, являются элементами предложений, сочетаний. В них представлены софты и файлы. Они могут отображаться в виде списка (list) или атомов (atom).
Несколько поочередно идущих абзацев составляют каталог. Они обязательно разделяются пробелами и замыкаются в скобки.
Составляющими одних перечислений могут служить другие, более мелкие, подпункты. Символьные структуры разной формы и уровня сложности можно создавать благодаря произвольной углубленности и вложенности. Существует пустая строка, она обозначается – () и называется «nill». При возведении информационной структуры, а также при способе управления ею, она играет особенную роль, представляясь одновременно и атомом, и списком.
Язык LISP относится к языкам программирования, которые используются для создания дополнительных загрузок к ПО по проектированию и моделированию. Для их использования необязательно хорошо разбираться в компьютере на уровне профессионала.
После изучения основных принципов работы в таких пакетах, как AutoCAD или ZWCAD Professional, который является аналогом ACAD, появляется необходимость упростить выполнение длительных рутинных операций или полностью избавиться от них. Для этого дополнения и нужны. Если они написаны на ЛИСПе, скрипты называются LISP-приложения.
Каждое из них представляет собой текстовый файл с определенным встроенным кодом для выполнения команды и подсказками от производителя. Определитесь с нужными для работы свойствами, выбирайте надстройку, скачивайте ее и загружайте в ZWCAD или другую платформу. Начиная с версии ZWCAD 2020, в платформу встроен Отладчик Lisp приложений, разработанный на базе Visual Studio Code от Microsoft.
Рассмотрим возможности одного такого модуля на образце скрипта «Выравнивание текстов».
Источник: www.zwsoft.ru
Что такое Lisp
Когда мы рассказывали про функциональное программирование, то привели в пример несколько языков, которые подходят для этого лучше всего. В этом списке есть особенный язык — Lisp. Особенный он потому, что именно с него и началось всё функциональное программирование.
Что такое Lisp
Lisp — это язык программирования, который сейчас используется для обработки и анализа данных. Язык очень старый, но иногда используется и сейчас для узкоспециализированных задач типа машинного обучения.
Язык высокоуровневый, то есть код написан более-менее человеческим языком и поддерживает сложную логику и работу со строками и числами в привычном нам формате.
Что работает на Lisp
На Lisp написан софт, который мониторит состояние самолётов — например «Боингов» и «Эйрбасов». Также Lisp лежит в основе софта, который анализирует и распределяет ресурсы в лондонском метрополитене.
На Lisp работает система обработки данных Apache Storm, текстовый анализатор Grammarly. На этом же языке сделан Circle CI — система постоянной выкатки новых версий софта (CI/CD).
А ещё Lisp используется тут:
- AutoCAD — язык использует внутренние команды для автоматического проектирования.
- Emacs — многофункциональный текстовый редактор, в котором Lisp выступает и как язык, на котором написан сам Emacs, и как язык внутренней обработки текста.
- Audacity — программы для работы со звуком.
На Lisp не пишут игры и приложения, это не язык для создания сложных экранных интерфейсов или быстрого прототипирования мобильных приложений.
Как и зачем появился Lisp
В 1950-х программисты и математики вплотную начали работать над искусственным интеллектом. Нейросети тогда были чисто математической моделью без практического применения, поэтому учёные взяли за основу такую идею:
Чтобы искусственный интеллект работал как настоящий, он должен быть устроен точно так же. А раз наш интеллект основан на мыслях, которые мы можем выразить словами, то нам нужно научить компьютер разбираться в словах, их смыслах и взаимосвязи между ними. Проще говоря, чтобы компьютер мог выразить свою мысль словами точно так же, как это делает человек.
Все наши мысли можно сформулировать в виде предложений, которые состоят из слов, а слова — из букв. Получается, что искусственный интеллект должен легко оперировать словами и символами и знать, в каком порядке их надо выстроить.
В то время ни один из существующих языков не позволял работать со строками и символами на таком уровне, поэтому Джон Маккарти в 1958 написал первую версию языка Lisp. Это название — сокращение от LISt Processing language, что переводится как «язык обработки списков». Списком может быть что угодно: символ, слово, предложение, другой список или даже список функций.
Пример кода
Чтобы сразу было понятно, чем этот язык отличается от других, вот два примера кода на Lisp. Первый обрабатывает два комплексных числа:
; функция сложения двух комплексных чисел (defun AddCom(Com1 Com2) (cons (+ (car Com1)(car Com2)) (cons (+ (cadr Com1)(cadr Com2)) NIL))) ; функция вычитания двух комплексных чисел (defun SubCom(Com1 Com2) (cons (- (car Com1)(car Com2)) (cons (- (cadr Com1)(cadr Com2)) NIL))) ; функция сравнения двух комплексных чисел (defun EqCom(Com1 Com2) (and (= (car Com1)(car Com2)) (= (cadr Com1)(cadr Com2)))) ; функция умножения двух комплексных чисел (defun MultCom(Com1 Com2) (cons (- (* (car Com1)(car Com2)) (* (cadr Com1)(cadr Com2))) (cons (+ (* (car Com1)(cadr Com2)) (* (cadr Com1)(car Com2))) NIL))) ; функция деления комплексных чисел (defun DivCom(Com1 Com2) (let ((z (+ (* (car Com2)(car Com2)) (* (cadr Com2)(cadr Com2))) )) (cons (/ (+ (* (car Com1)(car Com2)) z)(* (cadr Com1)(cadr Com2))) (cons (/ (- (* (cadr Com1)(car Com2)) z) (* (car Com1)(cadr Com2))) NIL )))) ; вычисление суммы чисел 2+3i и 1.5-8i (AddCom ‘(2 3) ‘(1.5 -8)) ; вычисление произведения чисел 3-i и 3+i (MultCom ‘(3 -1) ‘(3 1))
А вот код, который сам анализирует с точки зрения математики введённую строку и выполняет все математические операции:
(Defun weight (x) (COND ((EQ x ‘+) 1) ((EQ x ‘-) 1) ((EQ x ‘*) 2) ((EQ x ‘) 2) ((EQ x ‘/) 2) ((EQ x ‘^) 3) (T 5)) ) (Defun opcode (op) (COND ((EQ op ‘+) ‘+) ((EQ op ‘-) ‘-) ((EQ op ‘*) ‘*) ((EQ op ‘) ‘) ((EQ op ‘/) ‘/) ((EQ op ‘^) ‘^) (T (RAISEERROR (STRCAT «Неверен код операции » (OUTPUT op))))) ) (Defun inf-aux (ae operators operands) (inf-iter (CDR ae) operators (CONS (CAR ae) operands))) (Defun inf-iter (ae operators operands) (PROG NIL (COND ((AND (NULL ae) (NULL operators)) (RETURN (CAR operands)))) (COND ((AND (NOT (NULL ae)) (OR (NULL operators) (GREATERP (weight (CAR ae)) (weight (CAR operators)))) ) (RETURN (inf-aux (CDR ae) (CONS (CAR ae) operators) operands)))) (RETURN (inf-iter ae (CDR operators) (CONS (LIST (opcode (CAR operators)) (CADR operands) (CAR operands)) (CDDR operands)))))) (Defun inf2pref (x) (PROG (hd tl cc xx rr) (COND ((atomlist x) (RETURN (inf-aux x NIL NIL)))) (SETQ rr NIL) (SETQ xx x) LOOP (SETQ hd (CAR xx)) (SETQ tl (CDR xx)) (COND ((memb hd (QUOTE (SIN COS LOG EXP ATN ASN ACS SH CH SQR SIGN ABS))) (PROGN (SETQ rr (APPEND rr (LIST (LIST hd (inf2pref (CAR tl)))))) (SETQ tl (CDR tl)))) ((ATOM hd) (SETQ rr (APPEND rr (LIST hd)))) (T (SETQ rr (APPEND rr (LIST (inf2pref hd)))))) (COND ((NULL tl) (RETURN (inf-aux rr NIL NIL)))) (SETQ xx tl) (GO LOOP))) (Defun CalcExpr (expression) (EVAL (inf2pref (PARSE expression))))
Штука в том, что математических символов может быть сколько угодно и они могут стоять в любом порядке — Lisp их все найдёт, проанализирует, сам выстроит как нужно, посчитает и выдаст ответ. А всё потому, что этот язык изначально был заточен на обработку строк и символов.
Вот что получится, если запустить второй пример и попробовать вычислить несколько выражений:
(calcExpr «5+(7-4)*5»)
==> 20
(calcExpr «(sin(1))^2+(cos(1))^2»)
==> 1.000000000000000E+0
Особенности языка
Скобки и списки. Про скобки в Lisp есть тысячи мемов и шуток, а всё потому, что круглые скобки — это обозначение списка. В Lisp в списке может быть что угодно: другие команды, слова, символы, функции, списки в списках и так далее. И всё это может быть даже внутри одного списка, а потом передаваться в работу в качестве параметра в другой список.
Функции можно объявить где угодно. Действительно где угодно — даже в середине строки (которая в Lisp — тоже список, который будет обработан). Код из-за этого может стать менее читаемым, но если вы пишете на Lisp, то читаемость любого кода для вас вообще не проблема.
(defun назвать (name lv) (eval (cons ‘defun (cons name (cdr lv))))) (назвать ‘сложить ‘(lambda (x y) (+ x y))) (сложить 5 7) ==>12
Создание своих правил. Главная задача языка Lisp – обработать ваши списки по вашим же правилам. Это самая суть функционального программирования: вы задаёте правила обработки, а язык сам разбирается, как и где их применить, куда передать результат и что с ним делать дальше.
В чём хорош Lisp
Суперсила классического Lisp – в его умении работать с текстом: разбирать его на составляющие, искать связи, делать выводы и всё такое. При этом текстом может быть что угодно:
- обычный текст;
- статьи и базы знаний;
- код на других языках;
- внутренние команды какой-то программы, например AutoCAD;
- команды для станков;
- управляющая последовательность байтов на сервере;
- база данных.
Сейчас чаще используют Common Lisp — потомок оригинального языка, в который добавили новые команды, структуры данных и возможности для императивного программирования. Common Lisp можно применять везде, где есть правила обработки данных — от медицины и работы над геномом человека до внутренних систем передачи данных внутри интернет-провайдера.
Источник: thecode.media
Язык программирования Lisp: в чем его уникальность
Язык программирования Lisp относится к функциональной парадигме. Он является очень необычным вариантом с уникальными возможностями. Так, например, некоторые его называют программируемым языком программирования, так как необходимая библиотека может быть взята из любого другого языка.
Ранее Lisp использовался как родной, основной язык ИИ. Сейчас он таковым не является, но до сих пор успешно применяется в других сферах. Интересный факт: Lisp считается лучшим хакерским языком. Как он появился, где его использовали ранее и зачем – сейчас, вы узнаете из нашего материала.
История создания языка программирования Lisp
Lisp представляет собой один из самых старых языков программирования. Кроме того, он является первым функциональным, получившим большую популярность. Создание его ядра приходится на 60-е годы предыдущего столетия – разработчиком стал ученый Дж. Маккарти.
Основополагающая структура данных языка Lisp – список, откуда и пошло наименование языка. Широкую известность Лисп получил в 70-80-е годы ХХ века. В то время он использовался в качестве базового языка для научной деятельности в сфере искусственного интеллекта.
С учетом того, что сфера ИИ всегда предполагала большие траты ресурсов, а мощности компьютеров 80-х годов, очевидно, уступали современным, создатели Lisp пытались извлечь из языка максимум эффективности. Со временем Lisp приобрел небывалую ауру, а произошло это по двум причинам:
- В середине 70-х годов прошлого века исследователи в области ИИ ощутили недостаток мощности собственных компьютеров, и инженер Питер Дойч из MIT озвучил идею создания компьютера с упором на программы Лисп. В 80-е фирма Symbolics произвела ряд Lisp-машин, которые были специально заточены под этот язык. Таким образом Лисп стал связан с мощными программами для ИИ. В то же время создатели Lisp-машин и исследовательские отделы в области искусственного интеллекта стали предлагать свои варианты языка. Таким образом у Лисп образовалось много разновидностей (диалектов), что означало разделение языка. Дабы это предотвратить, в 1981 году несколько хакеров положили начало работе по созданию единого языка — Common Lisp, который включал в себя все лучшие стороны имеющихся версий.
- В 1985 году ученые MIT Харольд Абельсон и Джеральд Сассман выпустили книгу «Структура и интерпретация компьютерных программ», которая в хакерском сообществе более известна как Wizard Book («Книга волшебника»). С помощью этого учебника студентам MIT больше 20 лет преподавали программирование на Scheme, разновидности языка Lisp. Только за счет него Лисп стали рассматривать в качестве языка, с помощью которого возможно постичь сложные философские теории программирования.
Спад известности произошел в конце 80-х. В те времена исследовательская деятельность в сфере ИИ сместилась на периферию, а бюджетные и мощные компьютеры заполонили рынок и заменили Lisp-машины. Возрождение известности наступило после публикации эссе Пола Грэма, где он нарек его «лучшим языком для стартапов». В 1995 году автор со своим другом создал организацию Viaweb и выпустил одноимённый конструктор онлайн-магазинов, который был написан на Лиспе.
«Нам понравилась идея использования Lisp, так как это, на наш взгляд, могло сделать продукт более функциональным относительно конкурирующих компаний и позволило бы добавлять фичи, которые им недоступны. За счет того, что Lisp является языком высокого уровня, мы получим возможность обойтись без большой команды разработчиков и сберечь финансовые ресурсы» – такое заявление сделал Пол Грэм, сооснователь Y Combinator, создатель Hacker News.
Только до 25 декабря —>
Пройди опрос и
получи
обновленный
курс от Geekbrains
Дарим курс по digital-профессиям
и быстрому вхождения в IT-сферу
Чтобы получить подарок, заполните информацию в открывшемся окне
Для некоторых людей слова Грэма оказались убедительными, но их было очень мало. Если верить статистике GitHub, Emacs Lisp занимает 25-е, а Common Lisp — 49-е место по степени распространенности среди пользователей веб-сайтов. Между тем самые выдающиеся его стороны проявились в других языках: например, Python позаимствовал генератор списков, а C# унаследовал язык интегрированных запросов LINQ.
Lisp — второй после Fortran из «оставшихся в живых» устаревших языков программирования. В индексе TIOBE за декабрь 2021 года Лисп стоит на 31 месте, расположившись выше Lua, Scala и TypeScript.
Даже при том условии, что Lisp лишился лидирующей позиции в списке языков программирования задач ИИ, он смог остаться пригодным для изучения функционального программирования. Доступность и прозрачность синтаксиса совмещаются в нём с мощностью языковых средств и естественностью его расширения. Одним из ярких свойств Лиспа является общая синтаксическая форма написания программ и данных, благодаря чему можно обрабатывать структуры данных как программы и совершенствовать программы как данные.
Ключевые особенности языка программирования Lisp
Представим основные отличия Lisp от стандартных языков программирования:
- Формы предоставления программ и обрабатываемых данных в Лисп тождественны и представляют собой списочные структуры. За счет этого обнаруживается ряд интересных возможностей – к примеру, взаимодействие одной программы с другими. Кроме того, можно выделить универсальность, расширяемость и масштабируемость самого синтаксиса. Ядро LISP, прописанное на Лисп, располагается в рамках 200 строк, а интерпретатор ПРОЛОГа занимает чуть больше 50 строк.
- Реализация списков дарит возможность не тратить время на управление памятью, а сохранение и очищение ячеек осуществляется динамически. За счет этого сборщик мусора появился уже в первых вариациях языка. Lisp не имеет структуры строго типизированного языка программирования. Сегодня это не поражает воображение, но необходимо заметить, что на стадии начального развития данная концепция была антагонистом типизированному Фортрану.
- Благодаря префиксной нотации появляется больше возможностей для синтаксического разбора выражений. Более того, можно использовать общий списочный контекст и для программ, и для данных.
- Использование множества скобок, за счет чего наряду со стандартной расшифровкой «LISP» как «LISt Processing» имеет место и «Lots of Idiotic Silly Parentheses».
- Немаловажным фактом является существование Lisp-машин – вычислительных машин, устройство которых было адаптировано для результативного выполнения программ на языке Лисп. Эти аппараты не очень популярны – их численность во всем мире не превышает 10 000. Lisp-машины исследовательского центра Xerox стали родоначальниками некоторых общеизвестных идей и технологий: сборка мусора, лазерная печать, многооконные системы и др.
Алфавит и атомы языка программирования Lisp
Языки программирования создаются для кодирования команд, выполняющихся компьютером. Благодаря этому устройство может обрабатывать текст, воспроизводить графику и звук, создавать расчеты и многое другое. При этом процессор компьютера обычно не может выполнять сложные команды. По этой причине их нужно трансформировать под процессор.
Но есть и другой метод, для которого программу не нужно менять под команды процессора, вместо этого он поступает на вход программы-исполнителя (то есть интерпретируется). Такой принцип действия как раз и присущ Лиспу.
Для удобства назовем Lisp-машиной программу, которая выполняет команды Лиспа. Изначально пользователь мог взаимодействовать с этим языком программирования за счет запросов и ответов. Но сейчас имеется два варианта реализации Лисп-машины: диалоговый и пакетный.
Второй способ взаимодействия подразумевает старт Lisp-машины, считывание команд из определенного источника (скажем, из файла), выполнение данной команды и завершение Лисп-машины. Чтобы овладеть языком Lisp, нужно помнить, что программа в этом случае будет состоять из команд, которые выполняются Лисп-машиной.
ТОП-30 IT-профессий
2022 года с доходом
от 200 000 ₽
Команда GeekBrains совместно с международными специалистами по развитию карьеры подготовили материалы, которые помогут вам начать путь к профессии мечты.
Подборка содержит только самые востребованные и высокооплачиваемые специальности и направления в IT-сфере. 86% наших учеников с помощью данных материалов определились с карьерной целью на ближайшее будущее!
Скачивайте и используйте уже сегодня:
Источник: gb.ru
Lisp программа что это
Библиотека сайта rus-linux.net
apt-get install clisp и CLISP будет у вас установлен автоматически. Для других дистрибутивов (Fedora, OpenSUSE и т.д.), вы можете воспользоваться стандартными пакетами, перечисленными на сайте CLISP в разделе «Пакеты для Linux» (если они отсутствуют в репозиториях дистрибутивов).
Запускаем его
Чтобы запустить CLISP, выполните в командной строке команду clisp . Если все пойдет по плану, то вы увидите приглашение к работе, показанное на рис.1.
Рис.1: Запуск CLISP
Точно также как и во всех средах Common Lisp, в среде языка CLISP после того, как вы его запустите, произойдет переход в режим «ввод — вычисление — выдача результата» (read-eval-print-loop, который называется циклом REPL). Это означает, что вы можете сразу же начать вводить код на языке Lisp. Попробуйте, набрав для этого строку (* 7 (+ 4 3)) . Ниже под набранным выражением вы увидите результат:
> (* 7 (+ 4 3)) 49
В выражении (* 7 (+ 4 3)) символы * и + называется операторами, а числа 7, 4 и 3 называются аргументами.
В повседневной жизни мы должны были бы писать это выражение как ((4 + 3) * 7), но в Lisp мы первым помещаем оператор, за которым идут аргументы, а все выражение заключаем в круглые скобки. Это называется префиксной нотацией, поскольку на первом месте стоит оператор.
Кстати, если вы допустили ошибку и CLISP начнет вести себя ненормально, просто наберите команду :q и все будет исправлено. Если вы хотите завершить работу CLISP, просто наберите команду ( quit ).
А что под «капотом»?
Давайте не будем идти традиционным путем, начиная изучать с азов (изучение синтаксиса языка, его основных функций и т.д.). Иногда, выяснение деталей, лежащих в основе, оказывается более трудным, чем общее понимание возможностей. Конрад Барский (Conrad Barski) пытаясь заинтересовать нас языком Lisp, показывает, как на нем написать игру. Давайте воспользуемся его методом и напишем простую игру с интерфейсом из командной строки, в которой используется алгоритм двоичного поиска.
Мы знаем, что методика двоичного поиска представляет собое деление данных на две части, что постепенно сужает область поиска до тех пор, пока не будет найдено совпадение или пока для обработки не будет больше элементов. Это классическая игра на отгадывание чисел. Попросите вашего друга (или, лучше — вашего начальника, которые не силен в технологиях, и который кричал на вас в последний раз, когда вы уснули во время заседания) выбрать (в уме) число от 1 до 100 и ваша программа на Lisp-е отгадает его не более, чем за 7 итераций.
Вот как Барский объясняет игру:
Чтобы создать эту игру, нам нужно написать три функции: guess-my-number (отгадывание-числа), smaller (число-меньше) и bigger (число-больше). Игрок просто вызывает эти функции в цикле REPL. Чтобы вызвать функцию в Lisp, вы должны заключить ее в скобки, а также указать любые параметры, которые вы хотите передать в функцию. Поскольку для этих функций не требуется никаких параметров, мы, когда входим в них, просто заключает названия этих функций в скобки.
Стратегия этой игры следующая:
- Определяем верхний и нижний пределы (наибольшее и наименьшее значения) числа, задуманного игроком. В нашем случае, наименьшим возможным числом будет 1, а наибольшим числом будет 100.
- Отгадываем число между этими двумя числами.
- Если игрок говорит, что число меньше, то уменьшаем верхний предел.
- Если игрок говорит, что число больше, то увеличиваем нижний предел.
- Нам также нужен механизм, позволяющий начать все сначала с другим номером.
В Common Lisp функции определяются с помощью определения defun следующим образом:
defun function_name(arguments) . )
Когда игрок будет обращаться к функциям, которые составляют нашу игру, программе потребуется отслеживать нижний и верхний пределы. Чтобы делать это, нам нужно создать две глобальных переменных, которые будут называться *small* and *big* . Переменная, которая определяется в Lisp как глобальная, называется определением верхнего уровня. Мы можем с помощью функции defparameter создать новые определения верхнего уровня.
> (defparameter *small* 1) *SMALL* > (defparameter *big* 100) *BIG*
Звездочки, окружающие имена *big* и *small* , ласково называемые наушниками, выбраны совершенно произвольным образом и являются обязательными. Lisp рассматривает эти звездочки как часть имени переменной и игнорирует их как операции. У пользователей языка Lisp принято помечать глобальные переменные таким образом с тем, чтобы их можно было отличать от локальных переменных, которые будут рассмотрены в следующих статьях. Кроме того, когда Lisp читает ваш код, лишние пробелы и разрывы строк полностью игнорируется.
Теперь давайте определим первую функция, которая будет называться guess-my-number (отгадай мое число). В ней для отгадки числа, которое задумал игрок, будут использоваться значения переменных *big* и *small* . Определение будет выглядеть следующим образом:
> (defun guess-my-number() (ash (+ *small* *big*) -1)) GUESS-MY-NUMBER
Всякий раз, когда мы в цикле REPL запускаем фрагмент кода, подобный приведенному выше, в командную будет для введенного выражения выдаваться значение результата. В каждой команде в ANSI Common Lisp генерируется возвращаемое значение. Команда defun , например, просто возвращает имя вновь созданной функции. Вот почему после того, как мы обратились к defun , мы увидим в REPL имя функции, которое было нам возвращено.
Что делает эта функция? Как уже говорилось ранее, число, которое должен отгадать компьютер, будет лежать между двумя предельными значениями. Поэтому мы выбираем среднее значение, лежащее между двумя пределами. Но если среднее значение заканчивается дробной частью, мы будем использовать ближайшее к нему целое значение, поскольку мы отгадываем только целые числа.
Мы реализуем это в функции guess-my-number, добавив сначала цифры, которые представляют собой верхний и нижний пределы, затем с помощью функции арифметического сдвига ash делим пополам сумму пределов и сокращаем возможные результаты. Встроенная функция ash в Lisp берет число в двоичном виде и сдвигает его двоичные разряды влево или вправо, отбрасывая те биты, которые теряются в процессе сдвига. Например, число 11, записанное в двоичном формате, имеет вид 1011. Мы можем сдвинуть биты с помощью комады ash влево на 1 позицию, которая указывается в качестве второго аргумента:
> (ash 11 1) 22
Мы можем сдвинуть биты вправо (и отсечь бит, находящийся в конце), передав значение -1 в качестве второго аргумента:
> (ash 11 -1) 5
Давайте посмотрим, что происходит, когда мы вызываем нашу новую функцию:
> (guess-my-number) 50
Поскольку это наша первая догадка, то значение, которое мы видим, когда вызываем эту функцию, указывает, что все происходит так, как и планировалось: программа выбрала номер 50, который как раз посередине между 1 и 100. Теперь, давайте напишем наши функции smaller и bigger. Точно также как и функция guess-my-number, они являюся глобальными функциями, определяемыми с помощью defun :
> (defun smaller() (setf *big* (1- (guess-my-number))) (guess-my-number)) SMALLER > (defun bigger() (setf *small* (1+ (guess-my-number))) (guess-my-number)) BIGGER
Во-первых, давайте воспользуемся defun для того, чтобы начать определение новой глобальной функции smaller. Затем воспользуемся функцией setf для изменения значения глобальной переменной *big*. Поскольку мы знаем, что число должно быть меньше, чем последняя догадка, наибольший предел должен быть на единицу меньше, чем последнее значение, предложенное в качестве догадки.
Это вычисляется с помощью кода (1- (guess-my-number)) следующим образом: сначала вызывается наша функция guess-my-number, которая берет самое последнее значение, предложенное в качестве догадки, и с помощью функции 1- из результата вычитается 1.
Наконец, мы хотим, чтобы наша функция smaller показала нам новую догадку. Мы делаем это, поместив вызов функции guess-my-number в последней строке в теле функции. На этот раз функция guess-my-number будет использовать обновленное значение *big*, в результате она вычислит следующую догадку. Окончательное значение нашей функции будет возвращено автоматически, в результате чего наша новая отгадка (сгенерированная функцией guess-my-number) должна быть возвращена функцией smaller.
Функция bigger работает точно так же, за исключением лишь того, что она увеличивает значение *small* . Если вы, в конечном счете, вызываете функцию bigger, вы говорите, что ваш номер больше, чем предыдущие предположение, так что наименьшее значение, которое загаданное число может принимать (которое теперь будет представлено переменной *small* ), будет на единицу больше, чем предыдущая догадка. Функция 1+ просто добавляет 1 к значению, возвращаемому функцией guess-my-number.
Чтобы завершить нашу игру, давайте добавим функцию start-over, которая будет перезагружать наши глобальные переменные:
> (defun start-over() (defparameter *small* 1) (defparameter *big* 100) (guess-my-number))
Как вы видите, функция start-over перезагружает значения *small* и *big* , а затем снова вызывает функцию guess-my-number для того, чтобы выдать новую первоначальную догадку. Всякий раз, когда вы захотите начать совершенно новую игру с другим номером, вы можете вызвать эту функцию и перезагрузить игру.
На рис.2 наша игра показана в действии для случая, когда загадано число 74.
Рис.2: Игра в действии.
В следующих статьях мы вернемся к изучению с азов и начнем с базового синтаксиса и семантики языка.
Источник: rus-linux.net