Для чего нужен lisp

LISP. Атом первый

Привет, Хабр!
LISP заинтересовал меня уже давно, но, к сожалению, активно использовать свои знания и стремления на практике шанса не было. Скоро новый учебный год, а значит у меня опять будет возможность изучать и, уже второй год, преподавать студентам LISP. Еще одной проблемой, кроме традиционного отсутствия интереса к сложным вещам, кажется отсутствие литературы. Да и вообще, тема LISP-а в интернете, а тем более в рунете освещена слабо. Вот и на Хабре публикаций довольно мало.

Надеюсь, эта статья понравится общественности и откроет серию, повествующую об одном из наиболее интересных и наименее понятных (хотя до brainfuck и далеко) языков программирования – LISP. Ведь, как это не банально, еще один язык — еще одна жизнь

Начнем с базовых понятий LISP-а – атомов и списков. Немного позже, если будет интересно, в приквеле «Атоме нулевом» можно будет более подробно поговорить о философии и причинах возникновения LISP, а так же о современных направлениях его использования.

Краткая история

LISP был придуман Джоном Маккарти в 1958 году для решения задач нечислового характера и базировался на трех основных китах: алгебре списочных структур, лямбда исчислении, теории рекурсивных функций. Долгое время LISP использовался исключительно узким кругом специалистов по искусственному интеллекту. Но, начиная с 80-х годов прошлого века, LISP начал набирать обороты и сейчас активно используется, например, в AutoCad и Emacs.

Типы данных

Традиционно в LISP рассматривают два типа атомов: символы и числа. Символы могут обозначать числа, строки, сложные структуры, функции и другие объекты. Ограничения на имена символов зависят от используемого диалекта, но большинство из них не накладывает практически никаких ограничений на используемые в именах символы. Кроме того, опять же в большинстве диалектов, имена символов не зависят от регистра.
Некоторые символы имеют специальное назначение – это константы, встроенные функции, T (true, истина) и NIL (false, ложь).

Числа, в отличии от символов, не могут представлять другие объекты, таким образом число всегда является константным числом. Немного позже мы рассмотрим типы чисел в LISP.
Символы и числа представляют собой наиболее простые объекты LISP – атомы. Второй основной тип данных – точечные пары, которые синтаксически выражаются следующим образом:

Например, точечными парами являются выражения:

Атомы и точечные пары объединяют под общим названием S-выражения (S-expression, symbolic expression). Особым видом S-выражения является список, выражаемый следующим образом:

NIL в большинстве случаев определяется как пустой список, в таком случае определение списка можно переписать следующим образом:

Крылья, ноги… Главное хвост

И голова и хвост являются ключевыми понятиями в списочном контексте LISP. Первый элемент списка именуется головой списка, все остальные элементы – хвостом. Для работы с головой и хвостом существует набор базовых функций, рассмотренный немного ниже.
Пустой список эквивалентен паре пустых скобок:
NIL ().
Непустой список, состоящий из элементов a1, a2, a3… в соответствии с правилами записи S-выражений может быть записан следующим образом:

В LISP список можно записать и последовательностью элементов, заключенных в скобки и разделенных пробелами. По большему счету, список – это многоуровневая структура данных, для которой архиважна последовательность открывающих и закрывающих скобок.
Элементами списка могут быть атомы и списки, в том числе и пустой список. Например, () – пустой список, а (NIL) – список, состоящий из одного элемента NIL – что эквивалентно (()).
Следует понимать, что обычный синтаксис S-выражений может использоваться наравне со списочным синтаксисом, например, следующие выражение эквивалентны:

(a.(b.nil)), (a b.nil), (a b nil), (a b)

Если кому-нибудь интересно – можно будет рассказать и о внутреннем представлении списков в памяти. Это вполне самостоятельная и по интересу и по объему тема.

Основные функции и предикаты

В LISP существует довольно небольшой набор примитивных функций, обеспечивающий полноценную возможность обработки списков. В контексте списочных структур данные функции являются аналогом основных арифметических действий и образуют некую систему правил, к которой сводятся абсолютно все символьные вычисления.

Традиционном к базовым функциям относят QUOTE, CAR, CDR, CONS, ATOM, EQ.

Функция QUOTE

Для начала рассмотрим функцию QUOTE, предназначенную для блокирования вычисления выражения. Проще всего работу данной функции продемонстрировать простым примером:

Функцию QUOTE можно записать и короче:

Функция CAR

Предназначена для получения первого элемента точечной пары (или же головы списка). Использование данной функции возможно лишь в списочном контексте, использование для атома приведет к ошибке.

Для удобство головой пустого списка считается NIL.

Фунция CDR

Предназначена для получения второго элемента точечной пары (или же хвоста списка). Использование данной функции возможно лишь в списочном контексте, использование для атома приведет к ошибке.

Хвостом списка является весь список без первого элемента. Если список состоит из одного элемента, хвостом будет NIL. Хвостом пустого списка для удобства так же считается nil.
Несколько примеров:

Функции CAR и CDR реализованы во всех диалектах LISP, но в некоторых для них созданы и синонимы: FIRST и REST, HEAD и TAIL).

Функция CONS

Фактически функция CONS является антиподом функций CAR и CDR:

Функция ATOM

ATOM и EQ являются предикатами – т.е. функциями, проверяющих соответствие аргумента некоторому свойству и возвращающими T или NIL в зависимости от успешности проверки.

Предикат ATOM проверяет, является ли объект, переданный в качестве аргумента, атомом:

atom (S-выражение)

Функция EQ

Предикат, проверяющий идентичность двух символов.

eq (атом, атом)

Следует помнить, что предикат EQ применим лишь к атомарным аргументам и не может быть использован для списков. Так же не следует использовать EQ при сравнении чисел.

Более общим по сравнению с EQ является предикат EQL, позволяющий сравнивать однотипный числа:

Еще более общим для чисел является предикат =, позволяющий сравнивать значения чисел различных типов:

Более общим для списков является предикат EQUAL, позволяющий сравнивать идентичность двух списков:

Наиболее общим предикатом является EQUALP, позволяющий сравнивать произвольные объекты.

Функция NULL

NULL проверяет, является ли объект, переданный в качестве аргумента, пустым списком:

Судя по двум последним примером, можно сделать вывод, что функцию NULL можно использовать и как логическое отрицание. Для этих же целей в LISP существует и предикат NOT.

Что дальше?

Надеюсь, что смог заинтересовать. В следующий раз я планирую рассказать о существующих диалектах LISP (хотя на первых порах достаточно будет университетского XLisp), менее часто используемых базовых функциях, сворачивании CAR и CDR в что-то вроде CAAAADDAAR и определении собственных функций. Позже — рекурсия, управляющие структуры, область действия, ввод-вывод. Еще позже — если не надоем — о функционалах, макросах, свойствах символов и замыканиях. Ну и конечно, о том, о чем попросит общественность.
До встречи!

Источник

Преимущества Common Lisp

Для чего нужен lisp. Смотреть фото Для чего нужен lisp. Смотреть картинку Для чего нужен lisp. Картинка про Для чего нужен lisp. Фото Для чего нужен lispЛисп часто рекламируют как язык, имеющий преимущества перед остальными из-за того, что он обладает некоторыми уникальными, хорошо интегрированными и полезными фичами.

Далее следует попытка выделить набор особенностей стандартного Common Lisp, кратко и с примерами.

Эта статья, вероятно, будет больше всего полезна тем, кто имеет какой-то опыт в программировании, заинтересован лиспом и хочет лучше понять, что делает его таким привлекательным.

Текст по большому счёту основан на списке особенностей CL и обзоре CL Роберта Стренда (Robert Strandh).

Богатая и точная арифметика

Лисп предоставляет богатую иерархию числовых типов, которые хорошо интегрированы с остальными частями языка.

Длинные числа (bignums) создаются автоматически по мере надобности, что снижает риск переполнений и обеспечивает точность. Например, мы можем быстро вычислить значение 10↑↑4:

Рациональные числа представляются в виде дробей, так что никаких ошибок округления при их использовании не происходит. Точная рациональная арифметика интегрирована в язык:

Комплексные числа также являются встроенным типом данных в лиспе. Они могут быть представлены в виде краткого синтаксиса: #c(10 5) означает 10 + 5i. Арифметические операции также могут работать с комплексными значениями:

Обобщённые ссылки

Формы или позиции (places) могут использоваться так, как если бы они были отдельными изменяемыми переменными. При помощи SETF и других подобных конструкций можно изменять значения, которые концептуально связаны с заданной позицией.

Например, можно использовать SETF следующим образом:

Обобщённые ссылки работают не только в применении к спискам, но и ко многим другим видам структур и объектов. Например, в объектно-ориентированных программах один из способов изменить какое-то поле объекта — при помощи SETF.

Множественные значения

Значения могут быть объединены без явного создания структуры, такой как список. Например, (values ‘foo ‘bar) возвращает два значения — ‘foo и ‘bar. При помощи этого механизма функции могут возвращать сразу несколько значений, что может упростить программу.

Например, FLOOR — это стандартная функция, которая возвращает два значения:

По соглашению функции, которые возвращают несколько значений, по умолчанию используются так, как будто бы возвращалось только одно значение — первое.

При этом вы можете явно получить и использовать остальные значения. В следующем примере мы разделяем целую и дробную части PI при округлении:

Макросы

Макрос в лиспе — это своего рода функция, которая получает в качестве аргументов лисповские формы или объекты и, как правило, генерирует код, который затем будет скомпилирован и выполнен. Это происходит до выполнения программы, во время фазы, которая называется развёрткой макросов (macroexpansion). Макросы могут выполнять какие-то вычисления во время развёртки, используя полные возможности языка.

Одно из применений макросов — преобразовывать какой-либо исходный код в представление, корректное в терминах уже существующих определений. Другими словами, макросы позволяют добавлять новый синтаксис к языку (такой подход известен как синтаксическая абстракция).

Это позволяет с лёгкостью встраивать в лисп предметно-ориентированные языки (DSL), так как специальный синтаксис может быть добавлен в язык перед выполнением программы.

Основной выигрыш от использования макросов заключается в том, что они расширяют возможности языка, позволяя программисту выражать свои идеи проще и при помощи меньшего объёма кода. Можно добавить в язык новые средства так, как будто они являются встроенными. К тому же, если макросы использовать для предварительного вычисления данных или инициализации, они могут помочь в оптимизации производительности.

Макрос LOOP

Макрос LOOP — это мощное средство для представления циклов. На самом деле это целый небольшой встроенный язык для описания итерационных процессов. LOOP предоставляет все необходимые типы выражений для записи циклов, от простых повторений до итераторов и сложных конечных автоматов.

Функция FORMAT

Функция FORMAT поддерживает встроенный язык для описания того, как данные должны быть отформатированы. Помимо простой текстовой подстановки, инструкции FORMAT-а могут в компактном виде выражать различные правила генерации текста, такие как условия, циклы и обработка граничных случаев.

Мы можем отформатировать список имён при помощи такой функции:

FORMAT передаёт свой результат в указанный поток, будь то стандартный вывод на экран, строка или любой другой поток.

Функции высшего порядка

Функции в лиспе являются настоящими сущностными первого класса. Функциональные объекты могут динамически создаваться, передаваться в качестве параметров или возвращаться в качестве результата. Таким образом, поддерживаются функции высшего порядка, то есть такие, аргументы и возвращаемые значения которых сами могут быть функциями.

Здесь вы видите вызов функции SORT, аргументами которой являются список и ещё одна функция (в данном случае это #’

Источник

А вы знаете, где сейчас используется Лисп?

Введение

Лисп — второй по старшинству из ныне живых высокоуровневых языков программирования (после Fortran) и первый функциональный язык. Он был разработан в 1958 году и сильно изменился с тех пор, породив множество диалектов и оказав значительное влияние на развитие других языков. На данный момент наиболее известные диалекты: Common Lisp, Scheme, Racket и Clojure.

Для чего нужен lisp. Смотреть фото Для чего нужен lisp. Смотреть картинку Для чего нужен lisp. Картинка про Для чего нужен lisp. Фото Для чего нужен lisp
Слева: Лисп-машина в музее MIT.
Справа: Лисп-машина Symbolics 3640, фото Michael L. Umbricht и Carl R. Friend (Retro-Computing Society of RI)

Лисп стал “первооткрывателем” многих идей, нашедших применение в современных языках программирования: древовидные структуры, динамическая типизация, функции высшего порядка и многое другое. В этом посте мы не будем углубляться во вклад Лиспа в теорию, а сосредоточимся на практической пользе.

Изначально Лисп предназначался для работ в области искусственного интеллекта, в частности как представление математической нотации для символьных вычислений. Но насколько широко диалекты Лиспа используются сейчас и в каких областях применяются?

Мы в Typeable любим и применяем функциональное программирование, а влияние Лиспа на функциональные языки всё ещё сильно, поэтому нам стало интересно разобраться в этом вопросе.

Кто и что пишет на Лиспе?

Во время учёбы мне часто приходилось иметь дело с диалектами Лиспа. Проведя поиск информации при подготовке этой статьи, я была приятно удивлена, когда находила упоминание кода на том или ином диалекте Лиспа в приложениях, которыми пользуюсь сама. Думаю, и вы найдёте знакомые названия в этом списке.

Заключение

Я попыталась включить в список примеры из разных прикладных областей, инструменты для разработчиков, готовые приложения для нетехнических пользователей и системы, входящие в состав того, чем регулярно пользуется довольно большое число людей, даже не задумываясь об этом.

Конечно, это список не полный, здесь выделены наиболее интересные на мой субъективный взгляд применения Лиспа в современном ПО. Более полные списки библиотек, готовых приложений и компаний, использующих диалекты Лиспа, можно посмотреть в следующих ресурсах:

Рассказывайте в комментариях, какие программы на Лиспах используете и делитесь своими pet-проектами!

Источник

Must read. 5 свежих статей о языке Lisp

Подобрали 5 классных статей про успехи и неудачи Lisp, про его особенности и про то, как с ним работать.

Для чего нужен lisp. Смотреть фото Для чего нужен lisp. Смотреть картинку Для чего нужен lisp. Картинка про Для чего нужен lisp. Фото Для чего нужен lisp

Для чего нужен lisp. Смотреть фото Для чего нужен lisp. Смотреть картинку Для чего нужен lisp. Картинка про Для чего нужен lisp. Фото Для чего нужен lisp

Dana Moskvina / Skillbox Media

Каждую неделю мы отбираем для вас несколько свежих материалов из англоязычного интернета. В этом выпуске — самое интересное о Lisp.

Чем так крут Lisp?

Зачем читать: понять, чем Lisp очаровал своих фанатов, и сравнить с другими языками.

Интересное обсуждение для тех, кто не может понять, почему же люди любят Lisp. Это один из самых старых языков, но его активно используют и по сей день.

Самое главное качество Lisp, которое отметили в комментариях, — его гибкость и универсальность. В Lisp можно легко симулировать синтаксис других языков — его даже называют «программируемым языком программирования». Именно это делает его столь эффективным. Он позволяет каждому использовать свой подход и фактически собрать язык под свои нужды.

Другое интересное свойство — создавая программы на Lisp, можно достичь уникальной лаконичности и продуктивности.

Обсуждение будет интересно прочитать и тем, кто задаётся вопросом, какие качества языков программирования делают их по-настоящему крутыми.

Для чего нужен lisp. Смотреть фото Для чего нужен lisp. Смотреть картинку Для чего нужен lisp. Картинка про Для чего нужен lisp. Фото Для чего нужен lisp

В бэкграунде — программирование, французский язык, академическое рисование, капоэйра. Сейчас учит финский. Любит путешествия и Балтийское море.

Несколько причин перейти на Lisp

Зачем читать: узнать подробнее о классных фичах Lisp.

Лонгрид от давнего любителя Lisp: после долгих поисков идеального языка он пришёл к Lisp и сидит на нём уже четверть века. Вот пять функций, за которые автор полюбил этот необычный язык:

Конечно же, Lisp не волшебная пилюля, у него есть минусы, которые очевидны даже давнему фанату языка. Например, он всё меньше совместим с различными SDK, и с годами ситуация только ухудшается.

Автор подробно разбирает все плюсы и минусы языка, рассказывает о том, как они устроены, и щедро делится опытом.

Проклятие Lisp: спасётся ли Perl?

Зачем читать: узнать, почему Lisp непопулярен и наступит ли Perl на те же грабли.

Lisp хвалят за выразительность, гибкость и эффективность, но эти же качества его губят. Благодаря своей гибкости он подстраивается под нужды отдельных разработчиков, но в коммерческой разработке в энтерпрайзе это скорее вредит: сложно создать единую структуру, организовать и стандартизировать работу.

Более того, найти интегрированную среду разработки тоже непросто, поэтому для бизнеса Lisp далеко не самое привлекательное решение. В похожей ситуации оказался и Perl. Получится ли у него спастись от проклятия Lisp? Может быть, да. Сейчас в Perl появляются новые интересные фичи, которые могут его спасти, — но пока что хеппи-энд под вопросом. Кусаем локти и ждём финального сезона.

Зачем нужны макросы?

Зачем читать: разобраться, можно ли заменить макросы чем-то ещё.

Любители Lisp могут подолгу рассказывать о макросах и о том, что в C они совсем не те… Но что это такое и на самом ли деле они настолько незаменимы?

Макросы — это макрокоманды, и в первую очередь они нужны для автоматизации. Автор реализовал один и тот же механизм (подсчёт времени выполнения функции) на Python, Java и Clojure (диалект Lisp).

В первых двух случаях код приходилось встраивать в другое выражение — по-другому измерить его было невозможно. А вот в Clojure этого делать не пришлось: макрос просто использовали вместо функции. В статье есть и другие примеры использования макросов.

Lisp в веб-разработке

Зачем читать: чтобы не потеряться, начав заниматься веб-разработкой на Lisp.

С выгодами Lisp мы разобрались, но для всего ли годится такой старый язык? Что там насчёт веб-разработки? В небольшом гайде автор-фронтендер рассказывает, как создавать веб-приложения с помощью Lisp, какие фреймворки и тулы для этого понадобятся и каковы особенности процесса развёртывания в облаке, если оно не поддерживает Lisp.

Вот некоторые инструменты, которые пригодятся в работе:

Источник

Что конкретно может дать программисту знание языка Lisp?

Возможно кому-то вопрос покажется глупым и прошу пожалуйста не пинать, а запастись терпением и ответить или просто проследовать далее 😉

Мое видение lisp-программистов:
Последнее время то и дело посматриваю в сторону Lisp. В виду того что я человек сугубо практичный мне очень не хочется делать что-либо зря. Смотря на кого-либо изучающих различные Haskel, Lisp, Prolog, etc мне они кажутся людьми обладающими большим количеством свободного времени и желающих изучить чего-нить прикольное.

Суть вопроса: На сколько я прав?

Уточняющие вопросы: Это реально изучается только с целью «повернуть мозги» немножко в другую сторону, чтобы смотреть на свое ремесло, а разработка софта это все-таки ремесло, немножко под другим углом? Или это все-таки дает реальный практический смысл и позволяет решать на работе задачи (фраланс, на дядю, стартап)?

Меня интересует реальная практика!

ЗЫ:
Недавно меня спросили «А зачем вообще питон изучать?», ответил «Проще писать парсеры логов, небольшие анализаторы исходных кодов написанных на С++ или автосоздание хидеров, либо замена каких-либо строковых данных в С\С++ коде». Другими словами я могу привести реальную конкретную ситуацию где мне пригодился тот или иной инструмент, который я использую. Ровно с таким же мышлением и ищу людей знающих и применяющих Lisp, чтобы они мне показали свой опыт.

Оценить 1 комментарий

Для чего нужен lisp. Смотреть фото Для чего нужен lisp. Смотреть картинку Для чего нужен lisp. Картинка про Для чего нужен lisp. Фото Для чего нужен lisp

У каждого языка есть набор подходов к разработке, которыми в нем наиболее удобно пользоваться. Опыт использования языков с разными парадигмами разработки меняет мышление — вы можете сформулировать задачу разными способами.

Это, в итоге, оказывается полезным и при разработке на других языках.

С практической же точки зрения сейчас Lisp мало интересен. Насколько я вижу, сейчас на практике используют скорее Scala.

Вообще функциональные языки очень интересны. Их освоение для более-менее опытного программиста оказывается сложным (новичку их осваивать даже проще), из-за того, что многие привычные подходы в них оказываются неудобны. Но после освоения — оказываются даже проще в разработке чем объектно-ориентированные и процедурные.

Итоги:
1. Освоение функциональных языков полезно потому, что повысит скорость и качество разработки и на других языках (правда будет неприятный побочный эффект — от них станет подташнивать, когда окажется что вещь реализуемая в несколько строк на haskell требует несколько страниц бреда на C++).

2. Их очень удобно использовать в качестве скриптовых языков внутри более сложных продуктов (как тот же AutoLISP).

3. В крупных «enterprise» проектах их использовать нереально из-за того что мало разработчиков которые с ними знакомы, а для бизнеса заменимость сотрудников критически важна.

4. В небольших проектах, которые пишутся в одиночку — после освоения они могут дать заметно большую скорость реализации проекта. Соответственно, если заказчику все равно на чем сделано, лишь бы работало и работало хорошо, и оплата попроектная — функциональщик может банально зарабатывать больше.

5. Некоторые функциональные языки, например Haskell и OCaml обладают очень интересной и мощной системой типов, которая одновременно не так сильно путается под ногами как в Java, но при этом очень жесткая, и срезает множество потенциальных ошибок.

6. Ну и еще — например в JavaScript и Perl есть ряд инструментов, привычных для функционального программирования. Владение хотя бы одним функциональным языком программирования позволит писать более красивый код на этих языках.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *