LINUX.ORG.RU

Избранные сообщения alienclaster

Lisp Hackers. Бесплатная книга, содержащая интервью с разработчиками и пользователями Lisp

Новости — Документация
Группа Документация

Книга содержит интервью с 14 разработчиками и пользователями Лиспа.

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

( читать дальше... )

>>> Подробности

 , ,

rikardoac
()

Ручное управление памятью в лиспе

Форум — Development

Подскажите, пожалуйста, можно ли в лиспе работать с собственными структурами как в с++? Например вручную указать сколько памяти выделить для хранения и т.п. Гуглил, что можно делать как то через FFI, но ни одного примера не нашел, поэтому спрашиваю на данном форуме - можно ли управлять памятью программы и работать с указателями вручную?

 

a4eptp
()

Пакеты. Как должно быть?

Форум — Development

Как бы вы сделали, если бы проектировали систему пакетов с нуля. Или существующий вариант идеален?

 ,

monk
()

[lisp] несколько гадостей

Форум — Development

Пора всё же написать про лисп несколько гадостей (уже наболело).

1. По де-факто стандарту определение пространства имён и реализация этого пр-ва имён - это два разных файла. Т.е., как в С, а не как в Паскале. Это неудобно и вообще прошлый век.

Нет операции (with-namespace &body body) - может быть, её и можно сделать, но по-нормальному её можно сделать только через модификацию readtable. Но если две подсистемы меняют readtable и (не дай Бог) поменяют один и тот же символ, то между ними будет проблема и конфликт. Поэтому, для низкоуровневых вещей, которые потом предполагается включить в свой постоянный инструментарий, readtable менять нежелательно. А если импортировать множество разных мелких пр-в имён, то неизбежны конфликты при импорте. То есть, среда не поощряет создания множества мелких пространств имён, а поощряет создание небольшого числа крупных. А это плохо (жду конструктивных возражений).

2. Вообще, убогие пространства имён. Они не могут быть вложенными, как a::b::c. Только "плоские" пространства имён a::b В обычных языках, как правило, класс/структура задают пр-во имён. Собственно, если и есть в ООП какая-то сила, так это в том, что не нужно писать instance.field, а можно просто написать field, если находишься внутри метода. А вовсе не в том, что думают об этом апологеты ООП. В лиспе так написать нельзя (хотя есть конструкция with-slots, но в маленьких функциях она не помогает сократить код).

3. многословность. Сложение двух строк по стандарту (concatenate 'string "as" "df") а также в стандарте некоторым примитивным операциям присвоены имена, подобные destructuring-bind или multiple-value-bind

4. Вместо мойЛюбимыйИдентификатор нужно писать мой-любимый-идентификатор. Вроде мелочь, а места на экране жрётся море. Конечно, никто не заставляет, но есть проблемы с введением идентификаторов, чувствительных к регистру, поскольку в стандарте по умолчанию всё приводится к верхнему регистру и все стандартные символы - в верхнем регистре. То, есть, (print 'мойЛюбимыйИдентификатор) = МОЙЛЮБИМЫЙИДЕНТИФИКАТОР

5. Отсюда - следствие: В обычных языках пишем instance1.field1.field2 В лиспе (в лучшем случае) - (field2-of (field1-of instance1)) 4 лишних символа на каждую ссылку, не считая пробела, который тоже жрёт место на экране. Если брать голый, ничем не подслащённый стандарт, то может оказаться и (slot-value (slot-value instance1 'field1) 'field2)

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

7. Не хватает множества идиом. Например, есть push (деструктивно добавить элемент в начало списка). Но нет nconcf (добавить к переменной, содержащей список, другой список). Поскольку эти идиомы реально нужны, каждый вводит их по-своему и единый язык распадается на множество диалектов. То же сложение строк никто не делает как (concatenate 'string ...) Я ещё не вполне в культуре, но я не думаю, что есть де-факто стандарт на сокращённую запись этого выражения.

8. CLOS. Да, CLOS велик и могуч, в нём есть мультиметоды. Но в нём есть и такая фишка, как "изменить класс в рантайме". Это круто, но это - накладные расходы.

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

Конечно, да. Лисп велик и могуч и на нём можно делать то, что нельзя больше делать ни на чём другом. У него есть такие степени свободы, которые продвинутый си-плюс-плюсник просто никогда в жизни не сможет осознать. Но... Обычный язык общего назначения в лиспе нужно тоже делать DSL-ем. В том числе, нужен и DSL для полноценной работы со списками (а уж это - основа лиспа). DSL для удобного определения CLOS-классов. Каждый пишет такой DSL, но нет стандарта де-факто. Я об этом уже писал.

Последнее время я работаю с лиспом более плотно, чем раньше. Я уже начинаю сомневаться в целесообразности темы "лисп как препроцессор для С". Есть и практические к тому иллюстрации. Лисп сообщество не смогло по сей день решить некоторые тривиальные задачи:

1. asdf. Не умеет делать clean (т.е., нет стандарта на эту операцию). Не умеет пересобирать часть систем. Например, если я говорю recompile :force t своей системе, у меня пересобирается вся лисповая часть sbcl. И это - только одна из недоделок asdf. Т.е., при всей крутости лиспа, де-факто стандартное средство сборки гораздо слабее, чем make.

2. средства автодокументирования. Несмотря на то, что в лиспе делать автодокументацию на порядок удобнее, чем в каком-нибудь там С++, я не нашёл средства документированиия, подобного doxygen по мощности. Только не надо меня лечить, что есть describe и т.п. Документация удобна, когда она существует в виде книжечки. Один раз прочитал - и уже знаешь, куда тыркаться. Интерактивная помощь нужна, если что-то забыл, разбираться по ней не всегда удобно (хотя apropos рулит, конечно).

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

Я не ставлю себе цель обосрать лисп. На самом деле, я всё равно хочу писать на лиспе. Просто я давно пытаюсь понять - если он так крут, то почему же он уступил своё первое место мейнстрим-языка высокого уровня какой-то там Яве? Мне кажется, что я привёл здесь причины, основная из которых, если обобщать - лисп неудобен для простых вещей, в которых не нужны макросы. А этих простых вещей всё же больше. Видимо, при разработке следовало сделать более лёгким основной синтаксис. Создание макросов затруднилось бы, но макросов в коде обычно не больше 10-20%, так что общая трудоёмкость могла бы снизиться, а удобочитаемость заведомо повысилась бы.

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

>>>

 

den73
()

Главная концепция common lisp

Форум — Development

Ладно посмеялись и хватит. А вот кто мне сможет внятно объяснить, где применяется главная концепция common lisp - эквивалентность кода и данных? Макросы? Но это как-то приметивно, как мне кажиться. Жду примеров использования сей концепции, а то в сети как-то не густо

У меня уже есть соображение, почему это делается не часто и в такой форме, но я пока не буду раскрывать карты

mastercoder1
()

А как у common lisp дела с производительностью?

Форум — Development

Решил покурить cl ,не ну реально красивый язык. Учить решил по книге Practical Common Lisp (может посоветуете что ещё?), а запускать код на clisp. Ну так вот какие реализации языка предпочесть? Касаемо книг хотелось бы что то типа k&r, в такой же манере, но для common lisp, ну вы поняли.

Ну и вообще что посоветуете начинающему лисперу?

 

Dron
()

Посоветуйте минималистичный интерпретатор схемы

Форум — Development

Для организующих всякие данные скриптов - к производительности высоких требований нет, т.к. операции предполагаются элементарные, чтобы быстро стартовал, был способен грузить динамические библиотеки через ffi, желательна поддержка geiser для удобства разработки. Иными словами нужна замена clisp - CL уже приелся и хочу уже взглянуть на какой-нибудь r7rs, раздутый стандарт CL вроде меньше подходит для вышеназванных требований. Попробовал racket - не понравился, по ощущениям sbcl лучше отвечает требованиям не говоря уже про clisp.

 ,

ados
()

Вопрос про историю лиспа

Форум — Development

Мне понравилось замечание в SICP что у лиспа довольно специфичный взгляд на синтаксический сахар. Но вот я не могу понять почему в таких формах из CL как cl:defun или cl:destructuring-bind у ключевых симоволов &key, &optional приставка & вместо использования более адекватных для CL кейвордов?

 , ,

ados
()

Вышел Steel Bank Common Lisp 1.4.15

Новости — Open Source
Группа Open Source

Steel Bank Common Lisp, реализация языка программирования Common Lisp, обновился до версии 1.4.15.

( читать дальше... )

>>> Скачать

 ,

saahriktu
()

Алан Keй: deep flows in Lisp's logical foundations

Форум — Development

I could hardly believe how beautiful and wonderful the idea of LISP was. I say it this way because LISP had not only been around enough to get some honest barnacles, but worse, there were deep flaws in its logical foundations. By this, I mean that the pure language was supposed to be based on functions, but its most important components — such as lambda expressions, quotes, and conds — were not functions at all, and instead were called special forms ... My next questions was, why on Earth call it a functional language? Why not just base everything on FEXPRs and force evaluation on the receiving side when needed? I could never get a good answer

Далее Кей пишет о том, что эти размышления привели его к идее создания модели Ъ-ООП

А, все же интересно, кто-нибудь, таки, дал ответ на вопрос Алана Кея?

 

terminator-101
()

[ФП][срач] Язык программирования Pure

Форум — Development

Pure - динамически типизированный функциональный язык программирования с моделью исполнения, основанной на идее «term rewriting».

  • Синтаксис, бликий к Haskell (включая карринг, срезы, лямбды, сопоставление с образцом, list comprehensions и «as» patterns);
  • Поддерживает модель ленивости, основанную на продолжениях и заимствованную из Alice ML;
  • Допускает функции с побочными эффектами, опциональную аннотацию типов, интерфейсные типы
  • Поддержка рациональных, комплексных чисел, встроенный RegEx;
  • Содержит спектр встроенных структур данных, таких как: списки, туплы, векторы, матрицы и ленивые последовательности;
  • Интеграция с GSL;
  • Поддерживает полноценную систему гигиенических макросов;
  • Лёгкий FFI с сишными библиотеками;
  • Реализация под LLVM под GNU/Linux, Mac OS X, FreeBSD и Windows;
  • Из коробки поддержка компиляции в нативный код;
  • В комплекте идёт набор батареек для разнообразных нужд.

Про производительность заявляется следующее:

The Pure interpreter is able to achieve very good performance, offering execution speeds in the same ballpark as good Lisp interpreters. It seems to be one of the fastest implementations of term rewriting as a programming language right now, and is certainly good enough for most programming tasks except maybe the most demanding number crunching applications (and even these can be tackled by interfacing to Fortran or C).

Язык активно развивается, последняя версия документации датирована 8 января, автор постоянно пилит своё детище, активно идёт на контакт и охотно принимает и рассматривает любые предложения.

Ссылка на страницу проекта: http://code.google.com/p/pure-lang/
Ссылка на документацию (pdf): http://docs.pure-lang.googlecode.com/hg/puredoc.pdf
Ссылка на пример полной реализации АВЛ-деревьев: http://pure-lang.googlecode.com/hg/pure/examples/avltree.pure
Репозиторий (лицензия LGPLv3): hg clone https://code.google.com/p/pure-lang/

mix_mix
()

defmacro -> defun

Форум — Development

Допустим есть такой макрос:

(defmacro macro-test (alist ab &body body)
  `(loop for ,ab on ,alist
      do ,@body))

(macro-test '(a b c d) (a b) (format t "~s ~s~%" a b))
;; Выводит:
;; A B
;; B C
;; C D
;; D NIL
Можно ли как-то выразить тоже самое с помощью функции?
Пробовал так(не работает):
(defun defun-test (alist ab &rest body)
  (loop for ab on alist
     do (eval (cons 'progn body))))

(defun-test '(a b c d) '(a b) '(format t "~s ~s~%" a b))
;; Выдаёт:
;; Evaluation aborted on #<UNBOUND-VARIABLE A {10053A75D3}>.
Или нельзя?
// Просто интересно в качестве сферического коня в вакууме. Не надо спрашивать зачем оно мне нужно на практике :).

 

Bad_ptr
()

Кто сказал что оборачивание в скобочки это фи?

Форум — Development

Нука объясните ка мне, с чего вдруг массами стало считаться, что такой код

if (expr) {
  expr
} else {
  expr
}
это круто стильно молодёжно,
а вот такой код:
(if expr ;then
   expr ; else
  expr)
это — «фууу скобочки»?

Не является ли это просто следствием промывки мозгов основной массы кодеров авторитарными лидерами-программистами, такими как Страуструп? (Не знаю что там на счёт Ритчи, но сдаётся мне он не был на столько упорот и не заводил толпы программистов своими проповедями(но может просто у него не было возможности).)

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

И так, какие же плюсы несёт оборачивания в скобочки:
1) Унификация. Все выражения начинаются и заканчиваются скобочками.
2) Легко парсить.
3) Видно где начало/конец.
4) Легко рефакторить — надо перенести блок кода? Встал на открывающую/закрывающую скобку(на самом деле для умного редактора даже это не надо можно прямо изнутри выражения), нажал на кнопку — выделилось всё выражение, вырезал, перенёс куда надо.
5) Для автоматических манипуляций ака макросов это тоже удобно.
6) В будущем возможно создание умных инструментов, например умный структурный дифф, который не линии будет диффить, а понимать структуру, а потом умный просмотрщик таких дифоф сможет показать как от куда и куда перенесли это выражение и что там конкретно поменяли.
И т.д.

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

 , , , ,

Bad_ptr
()

Clasp, одна из новых реализаций CL, всего лишь в четыре раза медленнее, чем C++

Форум — Development

Новая реализация компилятора CClasp, базирующегося на Cleavir от Robert Strandh, без оптимизаций, всего лишь в четыре раза медленнее, чем C++. Ожидается, что с добавлением вывода типов производительность генерируемого кода с CClasp, должнo еще прибавить в скорости выполнения.

В приведенной таблице, также есть сравнение производительности генерируемого кода с SBCL (еще одна из активных реализаций CL) и Python.

Основной особенностью Clasp, среди других реализаций Common Lisp, является тесная интеграция с C++ и использование LLVM.

Подробности: https://drmeister.wordpress.com/2015/07/30/timing-data-comparing-cclasp-to-c-...

 , , , ,

Oxdeadbeef
()

Вышел Clasp 0.4

Новости — Open Source
Группа Open Source

20 ноября вышел в свет Clasp 0.4 — новый релиз, включающий в себя совершенно новый компилятор, способный генерировать до 200 раз более быстрый код, чем его предшественник, так же улучшено взаимодействие с C++ и теперь реализация полнее соответствует стандарту ANSI Common Lisp.

Clasp — новая реализация Common Lisp с упором на легкое взаимодействие с библиотеками C++, используя LLVM для компиляции в нативный код, с целью использования большого количества существующих библиотек и программ. Встраивание их в среду Common Lisp'а позволяет воспользоваться быстрым прототипированием, инкрементальной разработкой и другими возможностями, делающими Common Lisp столь мощным языком.

Основные изменения:

  • Совершенно новый, оптимизирующий/встраивающий (inlining) компилятор — cclasp! (небольшое сравнение с C++ / SBCL / Python)
  • Значения типов fixnum, character и single-float теперь представлены напрямую.
  • Указатели на объекты и cons-ячейки теперь тегируются для скорости.
  • Библиотека Clbind позволяет программистам выставлять наружу внешние C++-библиотеки.
  • Множество исправлений ошибок и улучшений.

>>> Подробности

 , clasp, , ,

loz
()

Арифметические/логические операции в sbcl

Форум — Development

Вот мне интересно, как sbcl проводит арифметические и логические операции. Вот как я себе это представляю:

1. Объявляются эти самые «known» функции в compiler/fndb.lisp

2. В compiler/target/float.lisp и compiler/target/arith.lisp определяются эти самые vop'ы для арифметических/логических операций.

3. При компиляции некоей функции, которая что-то, скажем, складывает, подставляется подходящий vop, или если это сделать нельзя, вызывается «generic-» функция, например generic-+ или generic-*. (как этот выбор происходит мне что-то не ясно)

4. В assembly/target/arith.lisp определяется эта «generic-» функция (которая на самом деле некая непонятная мне сущность assembly-routine). В ней происходит проверка (это уже в realtime), является ли аргуметы fixnum'ами. Если да, то операция проходит быстро (буквально в одну инструкцию) + возможный апгрейд до bignum.

5. Если хоть один операнд не fixnum, вызывается «статическая функция» two-arg-whatever, например two-arg-+. Они определены в code/numbers.lisp. В этом же файле определены «лисповые» арифметические функции. В «two-args-» происходит диспетчеризация по типам, что-то вроде внутреннего аналога typecase и непосредственно выполняется операция.

Ну вот вопросы такие:

1. Что же такое assembly-routine и в чём отличие от VOP?

2. Как подбирается нужный VOP и когда подставляется «generic-» функция?

3. А если я захочу ввести другой числовой тип (например, те же упакованные значения в SSE), что мне нужно будет дописать, чтобы их можно было складывать с помощью лиспового #'+? Есть что-то ещё кроме vop'ов и two-arg-'ов. Как правильно объявить тип, чтобы он был числовым? В compiler/generic/primtype.lisp вроде нет задания какой-либо иерархии.

4. И вообще про типы: primitive type похоже тоже на что-то для внутреннего использования. Видимо для того, чтобы определить, что значение этого типа может храниться в таких-то storage class'ах. А как объявляются «лисповые» типы?

Я думаю, тут такие спецы по sbcl, что разберутся в нем лучше авторов. Хорошо бы тут dmitry_vk и ловсана видеть, если они тут есть. А может ещё mv

 , , мировые открытия

shamaz
()

Про рестарты и интерактивность в CL

Форум — Development

Я тут посмотрел на свои старые проги и ужаснулся, какой я быдлокодер!

Вот у меня такая неприятная ситуация с flac-декодером, как обработка ошибок. Вначале flac файла есть несколько секций с метаданными (из которых обязательна, ЕМНИП, только одна - streaminfo). Я хочу сделать так, чтобы при возникновении ошибки в чтении метаданных пользователь мог бы пропустить битые данные и читать следующие. Пока сделано так:

Определены contitions:

(define-condition flac-error ()
  ((message :initarg :message
	    :initform ""
	    :type string
	    :reader flac-error-message)))

(define-condition flac-bad-metadata (flac-error)
  ((metadata     :reader flac-metadata
		 :initarg :metadata))
  (:report (lambda (c s)
	     (format s "Bad metadata: ~A"
		     (flac-error-message c)))))

В любом месте, где возникает ошибка, сигнализируем flac-bad-metadata (как, например тут):

(defmethod metadata-body-reader (stream (data padding))
  ;; Read zero padding bytes
  (let ((chunk (make-array (list (metadata-length data))
			   :element-type 'ub8)))
    (read-octet-vector chunk stream)
    ;; Do sanity checks
    (if (find-if-not #'zerop  chunk)
        (error 'flac-bad-metadata
               :message "Padding bytes is not zero"
               :metadata data))))

Где собираем полученные метаданные в список, делаем так:

       (setq last-block
             (restart-case
              (let ((metadata (metadata-reader bitreader)))
                (push metadata metadata-list)
                (metadata-last-block-p metadata))
              (skip-malformed-metadata (c)
                                       (let ((metadata (flac-metadata c)))
                                         (fix-stream-position bitreader metadata)
                                         (metadata-last-block-p metadata))))

Суть в том, что чтобы из места выше по стеку, где стоит restart-case пропустить плохие метаданные, нужно с места ошибки передать эти самые метаданные (там внутри инфа о том, как восстановиться). Я передаю их в слоте condition.

Но тут возникает такая проблема. Где-то, где программист должен принимать решение, что делать с возникшими ошибками, он может написать:

(handler-bind ((flac:flac-bad-metadata
                #'(lambda (c) 
                    (invoke-restart 'flac:skip-malformed-metadata c))))
              (multiple-value-setq (*a* *b*) (flac:open-flac *stream*)))

и получить список нормальных метаданных. А как ему это сделать интерактивно (через REPL/отладчик)? Суть такая, что в рестарт надо передать объект непосредственно с места ошибки, а restart-case задвинуть ниже по стеку не выйдет, иначе перемешается код читающий метаданные и код, предоставляющий стратегию восстановления.

 

shamaz
()

Mezzano - ОС на Common Lisp

Галерея — Скриншоты

Существует такая открытая ОС - Mezzano (ранее mezzanine), автор пишет просто из интереса видимо, понятно, что ни о каком реальном использовании сейчас речи не идет, но посмотреть интересно.

Ссылка на гитхаб: https://github.com/froggey/Mezzano

Лицензия у автора своя, которая в принципе позволяет делать с этим все что угодно, кому интересно - может почитать текст в репе.

На данный момент можно собрать образ для qemu и по желанию конвертировать его потом для virtual box.

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

Текущий код в гите видимо не очень рабочий, полностью у меня запустить ее так и не удалось, хотя сборка образа проходит нормально. Есть релиз demo1, с ним запускается.

Из приложений есть REPL, IRC клиент, небольшой редактор, косящий под EMACS, файловый менеджер - все ярлыки видно на скриншоте. Работать в этом нельзя, но посмотреть на код любителю common lisp должно быть интересно.

 ,

coredump
()

Что делает ООП - ООП?

Форум — Development

Как найти ту тонкую грянь которая разделит ОО-код от иного?
Какие вещи специфичны только для ООП?

 ,

Debasher
()

Почему Лисп умер.

Форум — Development

Очень часто в лисп-срачах на лоре можно наткнутся на аргументы лиспоненавистников, навроде «если лисп настолько крут, почему на нем не пишут энтерпрайз?» или «покажите мне годные приложения на лиспе». Также, иногда, встречаются жалобы, вроде таких: «Изучаю лисп на протяжении года, но пока не увидел значительных отличий от [some_lang]. Не понимаю, о какой-такой особенной мощи тут все говорят». Эти замечания, наверное, отчасти справедливы, во всяком случае, они основаны на реальном опыте.

Я нашел цитату Алана Кея сегодня, которая, наверное проясняет данный вопрос, чуть более чем полностью:

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

 ,

anonimous
()