Пользователь
0,0
рейтинг
24 апреля 2013 в 12:09

Разработка → Радикальный подход к разработке приложений из песочницы

От переводчика: В 2007 году, в поисках веб-движка я наткнулся на очень интересный и необычный диалект лиспа. И после прочтения нескольких статей я был очарован его принципами. Поскольку моя основная работа далека от веб-программирования, то профессионально я его не использую, но время от времени возвращаюсь к нему и понемногу «штурмую».

За всё время знакомства с этим языком он практически нигде не мелькает, и на русском языке информации о нем почти нет. Попробуем восполнить этот пробел. Несмотря на то, что оригинал статьи датируется 2006-ым годом, тема вполне актуальна.
Большое спасибо за помощь в переводе Надежде Захаровой и замечательному сайту Notabenoid.


1. Введение


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

Почти для всех этих проектов мы использовали Lisp. Моя ежедневная работа — слушать запросы заказчиков, анализировать бизнес-процессы и разрабатывать программное обеспечение соответственно их потребностям.

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

Это приходит во время итеративного процесса (некоторые называют его «экстремальное программирование»). Клиент оценивает каждую новую версию, затем обсуждаются стратегии дальнейшего развития программы. Нередко, непредвиденные требования вынуждают переписывать большие части проекта. Это не значит, что проект был плохо спланирован, потому что процесс, описываемый мною, и есть планирование. В идеальном мире разработка программного обеспечения — это только планирование, время, потраченное на непосредственное написание кода, должно стремиться к нулю.

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

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

Сначала мы хотим познакомить вас с Pico Lisp, объяснить, почему Pico на низком уровне значительно отличается от других Lisp-ов или систем разработки, а затем показать его преимущества на более высоких уровнях.

2. Радикальный подход


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

2.1. Миф 1: Lisp-у необходим компилятор


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

Идея интерпретируемого Lisp расценивается как старое заблуждение. Для современного Lisp требуется компилятор, а интерпретатор — это лишь полезное дополнение, и нужен для интерактивной отладки приложения. Он слишком медленный и раздутый для выполнения программ, которые уже находятся на этапе готовности к выпуску.

Мы же уверены, что верна противоположная точка зрения. С одной стороны (и не только с философской точки зрения) скомпилированная программа на Lisp больше не является Lisp вообще. Это нарушает фундаментальное правило «формальной эквивалентности кода и данных». Получившийся код не содержит S-выражений и не может быть обработан Lisp. Исходный язык (Lisp) преобразовывается в другой язык (машинный код) с неизбежными несовместимостями на разных машинах.

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

Но стоит ли это затраченных усилий? Конечно, скорость выполнения выше, и создание компилятора интересно в целях обучения. Но мы утверждаем, что в повседневной жизни хорошо спроектированный «интерпретатор» часто может превзойти скомпилированную систему.

Вы понимаете, что на самом деле мы не говорим об «интерпретации». Lisp-система сразу конвертирует передаваемые ей данные во внутренние структуры указателей, которые называются «S-выражениями». Истинная «интерпретация» работает с одномерными кодами символов, и это существенно замедляет процесс выполнения. Lisp же «вычисляет» S-выражения быстро следуя по этим структурам указателей. Нет никаких поисков, так что ничего на самом деле не «интерпретируется». Но мы будем придерживаться этого привычного термина.

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

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

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

Внутренние структуры Pico Lisp были изначально разработаны для удобства интерпретации. Несмотря на то, что они были полностью написаны на C, и не были специально оптимизированы для скорости выполнения, никогда не было проблемы недостаточной производительности. Первая коммерческая система, написанная на Pico Lisp, представляла собой систему для обработки и ретуширования изображений, а также для создания макетов страниц для печати. Она была создана в 1988 году и использовалась на Mac II с ЦПУ 12 МГц и оперативной памятью 8 МБ.

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

Чисто ради интереса я установил CLisp и сравнил его с Pico Lisp на примере простых тестов. Конечно, это не означает, что результаты тестов показывают полезность той или иной системы в качестве сервера приложений, но они дают приблизительное представление о производительности этих систем. Сначала, я попытался выполнить простую рекурсивную функцию Фибоначчи.
(defun fibo (N)
   (if (< N 2)
      1 
      (+ (fibo (- N 1)) (fibo (- N 2)) ) ) )

При вызове этой функции с параметром 30 (fibo 30), я получил следующие результаты (тестирование выполнялось на ноутбуке Pentium-I 266 МГц):

Pico (интерпретация) 12 секунд
CLisp интерпретация 37 секунд
CLisp компилированный 7 секунд

Интерпретатор CLisp почти в три раза медленнее, а компилятор чуть ли не в два раза быстрее Pico Lisp.

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

Поэтому я взял другой крайний случай, с функцией, выполняющей обширную обработку списков:
(defun tst ()
   (mapcar
      (lambda (X) (cons (car X) (reverse (delete (car X) (cdr X))))) 
      '((a b c a b c) (b c d b c d) (c d e c d e) (d e f d e f)) ) )

Вызвав эту функцию 1 млн раз, я получил:

Pico (интерпретация) 31 секунд
CLisp интерпретация 196 секунд
CLisp компилированный 80 секунд

Теперь интерпретатор CLisp более чем в 6 раз медленнее, но к моему удивлению даже скомпилированный код в 2.58 раз медленнее чем Pico Lisp.

Может быть, у CLisp медленный компилятор? И возможно код может быть ускорен с помощью некоторых трюков. Но эти результаты все равно оставляют много сомнений в том, могут ли быть оправданы накладные расходы на компиляцию. Возиться с оптимизацией компиляторов это последнее, что я хочу делать, когда дело касается логики приложения, и когда пользователь все равно не заметит задержек.

2.2. Миф 2: Лиспу Необходимо Множество Типов Данных


Функцию Фибоначчи, описанную в примере выше можно ускорить, объявив переменную N как целое число. Но тогда данный пример покажет, насколько сильно влияют на Lisp требования поддержки компилятора. Компилятор может выдавать более эффективный код, если типы данных жестко заданы. Common Lisp поддерживает много различных типов данных, включая различные целочисленные типы, типы с фиксированной/плавающей точкой, дробные числа, символы, строки, структуры, хэш-таблицы, а также векторные типы в дополнение к спискам.

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

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

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

На самом высоком уровне всегда можно эмулировать другие типы данных, используя эти три примитивных типа данных. Так, мы эмулируем деревья с помощью списков, строки, классы и объекты с помощью символов. Пока не наблюдается проблем с производительностью, зачем усложнять?

2.3. Миф 3: Динамическое связывание – это плохо


Pico Lisp использует простую реализацию динамического поверхностного связывания. Содержимое ячейки, хранящей значение символа, сохраняется при входе в лямбда-выражение или окружение связывания, и затем устанавливается новое значение. При возврате, оригинальное значение восстанавливается. В результате, текущее значение символа определяется динамически по истории и состоянию выполнения, а не по статическим проверкам лексической среды.

Возможно, для интерпретируемой системы это самая простая и быстрая стратегия. Для просмотра значения ячейки не требуется никаких поисков (требуется только доступ к значению ячейки) и все символы (локальные или глобальные) обрабатываются одинаково. С другой стороны, компилятор может выдавать более эффективный код для лексического связывания, таким образом, скомпилированный код на Lisp обычно все усложняет из-за поддержки нескольких типов стратегий связывания.

Динамическое связывание — это очень мощный механизм. Получить доступ к текущему значению можно из любого места, сама переменная и ее значение — это всегда физически существующие «реальные вещи», а не то что «кажутся» ( как в случае с лексическим связыванием, и в какой-то степени с использованием транзитных символов в Pico Lisp (смотри ниже)).

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

Существуют два типа ситуаций, когда результаты вычислений, использующих динамическое связывание, могут выйти из под контроля программиста:
  1. символ связан с самим собой, и мы пытаемся изменить значение символа;
  2. проблема фунарга (функционального аргумента), когда значение символа динамически изменяется сквозным кодом, который невидим в окружении текущего исходного кода.

Таких ситуаций можно избежать, используя транзитные символы.

Транзитные символы — это символы в Pico Lisp, которые выглядят, как строки (и часто используются в качестве строк), и которые лишь временно интернированы на время выполнения одного файла с исходным кодом (или только его части). Таким образом, они обладают лексическими возможностями, сопоставимыми со статическими идентификаторами в программах на языке C, только их поведение полностью динамическое, потому что они представляют собой нормальные символы во всех остальных отношениях.

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

2.4. Миф 4: Списки свойств — это плохо


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

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

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

Pico Lisp реализует свойства в виде списка пар ключ-значение. Единственная уступка в пользу оптимизации скорости — схема «наиболее недавно использовавшийся», немного ускоряющая повторяющийся доступ, но у нас нет конкретных признаков, что это было на самом деле необходимо.
Другой аргумент против свойств — их заявленная глобальная видимость. Это верно в той же степени, как то, что глобальны элемент в C-структуре или переменная экземпляра в Java-объекте.

Конечно, в глобальном символе свойство тоже глобально, но в типичной разработке приложений свойства хранятся в анонимных символах, объектах или элементах базы данных, которые доступны только в четко определенном контексте. Поэтому свойство «цвет» может быть использовано в определенном смысле в одном контексте, и в совершенно другом смысле в другом контексте, без всяких взаимных помех.

3. Сервер приложений


На базе этой простой машины Pico Lisp мы разработали вертикально структурированный сервер приложений. Он унифицирует движок базы данных (основанный на PicoLisp-овской реализации сохраняемых (персистентных) объектов как первоклассного типа данных) и абстрактный графический интерфейс (генерирующий, например, HTML или Java-апплеты).

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

Всякий раз, когда у сервера приложений запрашивается новый вид из БД, документ или отчет, или какой-то другой сервис, файл с исходным кодом Lisp загружается и выполняется на лету. Это аналогично URL-запросу с последующей отправкой HTML-файла в традиционном веб-сервере.

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

Эти Lisp-выражения описывают структуру GUI-компонентов, их поведение в ответ на действия пользователя и их взаимодействие с объектами базы данных. Короче говоря, они содержат полное описание программного модуля. Чтобы это было возможно, мы обнаружили, что важно строго придерживаться Принципа Локальности, и использовать механизмы «Префикс-классы» и «Демоны поддержки связей» (последние два описаны в другом документе).

3.1. Принцип Локальности


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

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

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

Этот язык должен иметь компактный синтаксис и позволять описывать все статические и динамические аспекты приложения. Локально, в одном месте. Без необходимости определять поведение в отдельных файлах.

3.2. Lisp


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

Только Lisp позволяет одинаково обрабатывать код и данные, и это основа модели разработки приложений на Pico Lisp. Он позволяет интенсивно использовать функциональные блоки и вычисляемые выражения, свободно смешиваемые со статическими данными и которые можно как передавать куда-либо, так и хранить во внутренних структурах данных во время выполнения.

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

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

В дополнение ко всему, поскольку Pico Lisp не делает формального различия между объектами базы данных и внутренними символами, все эти преимущества также применимы к работе с базой данных, приводя к прямой связи операций с GUI и БД в одном локальном контексте, используя идентичный код.

4. Заключение


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

Отчасти это было правдой. Но на сегодняшнем оборудовании скорость выполнения не имеет значения для многих практических приложений. А в тех случаях, когда имеет, кодирование нескольких критически важных функций на C обычно решает эту проблему.

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

Pico Lisp можно рассматривать как доказательство концепции «Меньше может быть больше».
Мамкин Мансур @mmans
карма
11,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (13)

  • +1
    Я обожаю LIsp, но для всех известных мне реализаций просто ужасно обстоят дела с библиотеками. Конечно, я могу дописывать свои на всех уровнях абстракции и это действительно очень круто, но с другой стороны это огромная куча времени — ведь библиотеки и их организация оттачиваются годами.

    И еще один момент — создание DSL для каждого проекта безумно интересно, но работая над несколькими сразу — опять таки хочется увидеть примерно одинаковые подходы и определения. Шаблоны, контроллеры и т.д. Да, это действительно может не иметь смысла для конкретного проекта, но на практике универсальность и паттерны нужны для взаимопонимания.

    Внимание, вопросы автору статьи:
    1. Достаточно ли для Pico Lisp стандартных библиотек (адаптеры к БД, к http-серверам, регулярки, сокеты, потоки (нити), web-клиенты и т.д.)?
    2. Насколько все это портировано на различные ОС?
    3. Существуют ли web-framework'и с очерченными определениями и стандартными подходами?
    4. Есть ли стабильные крупные проекты на Pico Lisp?
    • +5
      1. Автор проекта — противник разрастания PicoLisp всяческими библиотеками по принципу (чтобы было). На этот счет как-то была дискуссия в списке рассылки. Чем это компенсируется:

      a) Встроенная объектная БД очень гибкая и удобная, практически не ограничена по размерам, довольно удобный язык запросов (встроенная реализация Пролога — Pylog), плюс возможность организации распределенной БД, репликация.

      б) Простой FFI (foreign function interface), при необходимости несложно вызвать функции из DLL

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

      Потоки принципиально не используются, зато параллельные вычисления с помощью процессов широко применяются. А благодаря компактности VM и интерпретатора оверхед очень небольшой.
      Веб-клиент есть. Кстати, на Rosetta Code много примеров решения задач на PicoLisp.

      2. Основное требование — POSIX. На Linux, FreeBSD работает. Нативной версии под Win пока нет, никто не взялся. Есть версия интерпретатора на Java (Ersatz PicoLisp, но в ней скорее всего нет поддержки БД). Появилась 64-битная версия (в отличие от 32-битной версии переписана на ассемблере, который генерируется лиспом под различные архитектуры)

      3. Да, по сути PicoLisp это и есть (самодостаточный) веб-фреймворк со встроенной БД. В поставке есть «эталонный» пример ERP-приложения в 700 строк (в папке app/) и документация к этому примеру. По словам автора, все его приложения очень похожи на этот пример, просто намного больше классов, форм и т.п. Для конечного пользователя вид может быть совершенно разным, например soccer-analytics.com, но внутри та же самая структура.

      4. Опять же со слов автора, самый старый (и еще действующий) проект начат в мае 2001 г, и он же скорее всего самый большой.
    • 0
      кстати вот свежий пример, скриптинг на PicoLisp плюс web-клиент. Скрипт парсит перевод слова с сайта dict.leo.org. Насколько я знаю, автор PL для скриптов предпочитает использовать его вместо bash
  • +2
    Pico Lisp — штука интересная, а вот статья, честно говоря, не блещет. Какой-то очередной манифест за интерпретируемость против компилируемости.

    Ни одного примера, демонстрирующего именно те преимущества, которые появляются, если нет ограничений, необходимых для эффективной компиляции, но куча каких-то передергиваний на примерах, где интерпретируемые языки заведомо проигрывают.

    ради интереса я установил CLisp и сравнил его с Pico Lisp
    С каких это пор CLisp стал считаться компилируемым? То, что он компилирует в байт-код не отменяет интерпретации этого байт-кода. Сравнивайте хотя бы с SBCL тогда уж.

    не очень хороший пример типичной Lisp-программы. Она состоит только из примитивного потока и арифметических функций, что легко оптимизируется компилятором
    Ну да, поэтому мы не будем брать этот пример, на котором компиляция хорошо себя проявляет, а возьмем пример, где основное время уходит на управление памятью, а интерпретация/выполнение кода ~1% от всего времени.

    может быть написано прямо на C, если это критично по времени (в этом случае выполнение заняло бы всего 0.2 с)
    Лучшие компиляторы Lisp вполне приближаются по скорости полученного кода к C, особенно на вычислительных задачах. И говорить, что 30–60-кратное замедление не критично, нельзя.

    Миф 2: Лиспу Необходимо Множество Типов Данных
    Ну, если не обращать внимания на 60-кратное замедление, то можно и без всяких типов обойтись — компилятор сам разберется.

    С другой стороны, Pico Lisp поддерживает только три встроенных типа данных
    И можно сказать, что программа, частично написанная на C из-за недостатка скорости, написана на Lisp, а компиляторы, которые позволяют всю программу написать на Lisp, всего лишь дав компилятору подсказки в виде типов данных, не нужны.
  • 0
    Большое спасибо, понятно, есть вопросы/комментарии:

    а) Опять таки интересуют бенчмарки, т.е. понятно что для небольших проектов можно и в одном файле в списках базу сделать ((:a 1 :b «aaa» :c 0)… :-) Но меня интересуют именно высокие нагрузки и большие БД. Есть ли сравнительные тесты где-то?
    б) Ну это как раз то о чем я говорю, конечно WinAPI и Posix это очень круто, но это низкий уровень и не хочется для каждого проекта делать одно и то же. С другой стороны написание собственных библиотек без поддержки со стороны платформы означает очень высокий порог входа следующих программистов проекта.
    в) Эмм, нет не проще. Запуск процесса это огромная бессмысленная трата ресурсов. CGI никем не используется именно по этой причине, а если на каждый запрос еще и множественные процессы создавать…

    2. Жаль, люблю работать под Windows. Вообще проблема lisp-ов :-)
    3. Вот это интересно, думаю все же посмотрю. Опять таки повторюсь сразу и для 4 пункта, что 1 большой проект да, оправданно и удобно реализовывать на DSL, для нескольких важна узнаваемость.

    • 0
      вот что нашел по бенчмаркам: NeedForSpeed (свежее), database contest
      Суть: еще в 2006-ом PicoLisp занял в 2ое место в конкурсе по СУБД немецкого журнала c't
      Pico Lisp made the second place in the DB-Contest of c't magzine (c't
      13/06, pp. 190)!… And got an extra medal for the «most original and
      surprising program»

      По http-серверам: был период, когда выяснилось, что PL быстрее, чем TPD2.

      По поводу запуска процесса не соглашусь. Насколько знаю, PicoLisp использует fork запуска дочернего процесса, а у fork-а как раз небольшие расходы, поправьте если ошибаюсь.

      Насчет больших БД: автор упоминал как-то об одном проекте с БД около 500Гб, так что с размерами тоже все довольно неплохо. Вообще одним из принципов числится «Unlimited» — размеры структур искусственно не ограничены.
  • +1
    Динамическое связывание, списки, интерпретатор, отсутствие типов… Да это же LISP 1.5 из 1960-го!
    Сравнение с CLisp вообще умилило. Pico Lisp всего лишь в два раза медленнее самой медленной реализации Common Lisp.
  • 0
    Интересно, знаком ли автор с Clojure? Не совсем Lisp, с другой стороны нету проблем ни со скоростью, ни с библиотеками. Ну и конечно ФП — это круто.
    • 0
      Нет, говорит, только читал немного Clojure-кода на rostettacode.org. Да и смысл ему разбираться в Clojure, если у него есть свой инструмент, который вполне устраивает практически для всех задач, вплоть до замены bash-скриптов?
  • 0
    Ну вот, осталось самое главное.
    1. Как это правильно собрать под Win/Lin
    2. и красивые примеры использования в роли DB и HTTP сервера
    • 0
      Под Win — можно либо в Cygwin (неск. лет назад пробовал — у Cygwin толком не работали файловые блокировки, а без них multi-user БД в принципе не юзабелен). Но лучше я бы советовал глянуть в сторону coLinux или andLinux.
      На Linux:
      1) Качаем и распаковываем куда-нибудь в ~/picoLisp/ свежую тестовую версию
      2) Ставим gcc и с++
      3) Если нужен 32-битный интерпретатор, то (cd src && make picolisp) (для обучения и использования в интранет этого достаточно).
      Если нужно собрать 64-битный интерпретатор, то тут чуть посложнее — нужно или сначала собрать 32-битную версию, или иметь установленный Java-рантайм в системе, или (последний вариант), скачать software-lab.de/x86-64.linux.tgz и распаковать в src64/. Это объясняется тем, что 64-битный PicoLisp написан на «псевдоассемблере», из которого генерируется ассемблерный код под конкретную архитектуру процессора (на сегодняшний день поддерживаются x86-64, ppc64 и 64-битный эмулятор для x86). А для генерации как раз нужен работающий интерпретатор.
      Если коротко, то в первый раз 64-битную систему пробуем собрать так:
      
      $ (cd src; make)
      $ (cd src64; make x86-64.linux)
      

      Насчет красивых примеров — даже не знаю. Задачку надо какую-нибудь практическую. В планах еще PicoLisp tutorial перевести, но пока особого интереса к теме не наблюдаю
  • 0
    > у Cygwin толком не работали файловые блокировки, а без них multi-user БД в принципе не юзабелен
    Для пробы и/или разработки вполне терпимо. Правда у меня собралось несколько странно. Видимо был невнимателен.

    > Задачку надо какую-нибудь практическую.
    web-магазин по продаже подержанных депутатов :-)

    > но пока особого интереса к теме не наблюдаю
    Как правильно подмечено в анекдоте:
    … Сынок, так ты не немой? А почему же ты молчал?
    А меня раньше все устраивало!…

    Разработка ERP систем, да еще и на LISPе, согласитесь, не для всех. А у серьезных людей не всегда есть время на комментирования всего подряд. Работа, дети, общение с друзьями в off-line… Но в закладки вас это добавить совсем не помешало.
    • 0
      Для пробы и/или разработки вполне терпимо. Правда у меня собралось несколько странно. Видимо был невнимателен.

      Оно вполне могло сломаться за эти годы: под Cygwin специально никто не тестирует. Будет время — тоже гляну.
      web-магазин по продаже подержанных депутатов :-)

      Ого, у вас уже депутатов продают. Шутку оценил :)

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