LINUX.ORG.RU

lisp-lor-faq


1

6

Я решил, что кучи флейма по лиспу не должны пропасть втуне, а также принимая во внимание наличие на L.O.R. любителей лиспа, взял на себя смелость приступить к созданию FAQ по языку Lisp.

FAQ не завершён, фактически самое его начало в сыром ещё виде размещено здесь: http://www.linux.org.ru/wiki/en/lisp-lor-faq

Кому интересно и score > 100 - могут сразу присоединиться к его составлению, кому не хватает score могут оставить замечания здесь.

Ответ на: комментарий от Ritz

1. что с тредами под виндой?

2. аналог CLOS?

3. да ради бога, он имеет такое-же отношение к лиспам, как и схема с елиспом и прочими. К CL - никакого. Нравится - используй. Меня, в свою очередь, в своё время как раз насторожило, что его так красочно расписывали на примере хеловордовского гуя. Потом полез читать про отличия от CL, потом отзывы тех самых «олдфагов», и решил, что мне оно не надо. Но кто я, чтобы навязывать своё решение? =)

yyk ★★★★★
()
Ответ на: комментарий от Ritz

любопытно было бы взглянуть
как реализовать в newLISP
1. destructuring-bind
из Common Lisp
(часто используется)
2. syntax-rules
из Scheme
(это вообще реактивная вещь)

h1t
()
Ответ на: комментарий от Ritz

я увижу конкретный код, который на каком-нибудь старорежимном ЛИСП’е работает отлично

Ну вот, например. Если будет мало - пожалуйста, напишу еще.

(defclass organization ()
  ((name :initform "" :accessor :initarg :name :accessor organization-name)
   (employees :initform (make-array 0 :fill-pointer t :adjustable t) :accessor organization-employees)))

(defclass employee ()
  ((employer :accessor employee-employer :initform nil)
   (name :initform "" :initarg :name :accessor employee-name)))

(defun apply-to-job (employer employee)
  (setf (employee-employer employee) employer)
  (vector-push-extend employee (organization-employees employer)))

(let ((org (make-instance 'organization :name "ACME"))
      (worker (make-instance 'employee :name "Work Man")))
  (apply-to-job org worker))

(тут определяются два класса: organization и employee; у organization есть имя и массив работников; у работника есть работодатель)

Простой пример циклической структуры.

dmitry_vk ★★★
()
Ответ на: комментарий от Ritz

>передавать объекты по ссылкам в newLISP можно кучей разных способов

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

Система контекстов, опять-таки

Да-да, я слышал. Попытка заменить нормальные лексические переменные.

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

неужели? Цитата из http://www.newlisp.org/downloads/newlisp_manual.htm: «All objects — except for contexts, built-in primitives, and symbols — are passed by value and are referenced only once. When objects are no longer referenced, their memory is automatically deallocated.»

dmitry_vk ★★★
()
Ответ на: комментарий от h1t

1. По тредам. Там есть два варианта, как раз недавно разбирались.

Первый способ, классический:

(process "newlisp.exe my-proc.lsp")

Второй способ, имеющий некоторые преимущества:

(import "shell32.dll" "ShellExecuteA")
(ShellExecuteA 0 "open" "some-program.exe" "" 0 1)

Надо отметить, что оба решения имеют свои недостатки.

2. Что такое CLOS я не знаю.

3. Деструктинг-бинд есть.

> (apply cons (sequence 1 10) 2)
(((((((((1 2) 3) 4) 5) 6) 7) 8) 9) 10)
> (apply cons (sequence 1 10) 3)
(((((1 2) 4) 6) 8) 10)

Кстати, я всегда удивлялся, зачем destructing-bind нужен. На практике мне почему-то всегда хватает просто (apply * '(1 2 3 4 5))

4. syntax-rules, да, любопытная вещь. Не знаю, насколько макросы в newLISP могут то же самое. Другой вопрос, что я никогда не понимал — зачем нужно делать ещё один while или for, если они уже есть встроенные?

Ritz
()
Ответ на: комментарий от dmitry_vk

Посмотрел на код. Заодно выяснил, что такое CLOS. Вот ссылка на любопытное обсуждение: http://newlispfanclub.alh.net/forum/viewtopic.php?f=5&t=2319&p=12943&...

Суть дискуссии передана в цитате из Пола Грэма (<a href="http://www.paulgraham.com/noop.html">источник</a>):

«I personally have never needed object-oriented abstractions. Common Lisp has an enormously powerful object system and I've never used it once. I've done a lot of things (e.g. making hash tables full of closures) that would have required object-oriented techniques to do in wimpier languages, but I have never had to use CLOS».

Я, в общем, с Грэмом согласен. Какой смысл изобретать велосипед в виде базы данных, если есть удобный SQL? Или, для мелких масштабов, тупо текстовые файлы?

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

(define (update-file file-name line)
  (write-file file-name (join 
    (unique (append (parse (or (read-file file-name) "") "\n") (list line))) "\n")))

(define (apply-to-job employer employee)
  (update-file (append "EMP/" employer ".txt")
    (append "EMPLOYEE: " employee)))

(apply-to-job "ACME" "Work Man")
(apply-to-job "ACME" "Lazy Man")
Ritz
()
Ответ на: комментарий от Ritz

>2. Что такое CLOS я не знаю.

Мощнейшая ОО-система.

3. Деструктинг-бинд есть.

Это не destructuring-bind. destructuring-bind - это такая форма паттерн-матчинга на списках аргументов.

Я, в общем, с Грэмом согласен. Какой смысл изобретать велосипед в виде базы данных, если есть удобный SQL? Или, для мелких масштабов, тупо текстовые файлы?

При чем тут БД вообще? CLOS - это объектная система. SQL - это язык запросов к БД. Это совершенно разные вещи. Вы иерархию объектов игры тоже в файловой «БД» будете хранить? А как будете вызывать методы для объектов? Как наследование отображать?

подобные описанной

Какая задача была описана?

Я лишь показал пример кода, который не выразить в newlisp. Вместо этого тривиального примера можно рассмотреть любую иерархическую модель. Дерево виджетов; дерево синтаксического разбора; любая графовая структура; связи между игровыми объектами в игре - все это невозможно представить в newlisp. Тут речь про то, что автор языка не смог написать сборщик мусора (да, это сложная задача), но вместо того, чтобы признать это, превозносит это в виде уникальной мегафичи. То же самое с динамическим скоупом переменных - да, в чистом интерпретаторе его проще реализовать; но не надо это преподносить как очень хорошую вещь - от этого отказались много лет назад.

dmitry_vk ★★★
()
Ответ на: комментарий от Ritz

>Обычно делаю примерно так.

Задам всего два вопроса:

1) Как имея работника получить его организацию?

2) Как имея организацию получить всех ее работников?

3) Как иметь несколько организаций с одинаковыми названиями?

4) Как иметь несколько работников с одинаковыми названиями?

5) Как имея работника узнать его имя?

6) Как работнику поменять свое имя? Как организации переименоваться?

Если сможете ответить на эти (и многие другие вопросы) - да, у вас есть ОО-система. Не сможете ответить на хоть один из них (или любой многих других) - у вас нету ОО-системы.

dmitry_vk ★★★
()
Ответ на: комментарий от dmitry_vk

Вопросы-то знакомые, очень даже. Чтобы не сказать «до боли».

Можно, в общем, городить гигантские многоуровневые списки, прямо как описано в мануале:

(set 'persons '(
    (id001 (name "Anne") (address (country "USA") (city "New York")))
    (id002 (name "Jean") (address (country "France") (city "Paris")))
))

Потом из этих списков всё извлекается в два счёта.

(assoc '(id001 address) persons) → (address (country "USA") (city "New York"))
(assoc '(id001 address city) persons) → (city "New York")

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

Однако… лично мой (возможно, ошибочный) опыт показал, что хранить данные в списках не очень разумно. Так как LISP удобен именно для обработки данных, а не для их хранения.

Вот как решал бы заданные вопросы я:

1. Имея работника получить организацию:

(define (find-employee employee)
  (clean null?
    (map (fn (x) (if (regex (append "EMPLOYEE: " employee)
      (read-file (append "EMP/" x))) (0 -4 x)))
        (directory "EMP" "[^.]"))))

2. Имея организацию получить работника:

(define (all-employees employer)
  (find-all "EMPLOYEE: .+" (read-file (append "EMP/" employer ".txt"))
    (10 $0)))

3.4. Чтобы иметь несколько сотрудников/фирм с одинаковыми именами, надо добавить им ID. Как решать эту задачу без ID — я не очень понимаю. Причём не понимаю на уровне пользователей. Как, например, проводить инвентаризацию персонала, не имея какого-нибудь уникального кода?

5. На вопрос «как имея сотрудника узнать его имя» я решил не отвечать.

6. Как работнику поменять свое имя? Как организации переименоваться?

Вообще, в newLISP есть оператор set-ref-all, который именно для это служит:

(set 'data '((monday (apples 20 30) (oranges 2 4 9)) (tuesday (apples 5) (oranges 32 1))))

(set-ref-all 'apples data "Apples")

 → ((monday ("Apples" 20 30) (oranges 2 4 9)) (tuesday ("Apples" 5) (oranges 32 1)))

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

; Переименовать работника (во всех фирмах)
(define (rename-employee employee new-name)
  (map (fn (x)
    (write-file (append "EMP/" x ".txt")
      (replace "(?<=EMPLOYEE: ).+" (read-file (append "EMP/" x ".txt")) new-name 0)))
    (find-employee employee)))

; Переименовать организацию
(define (rename-employer employer new-name)
  (rename-file (append "EMP/" employer ".txt") (append "EMP/" new-name ".txt")))

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

Разные сложные системы каталожных ящиков нужны только обычным языкам, в которых поиск является проблемой. Зачем такая система нужна в LISP — для меня загадка. Проще говоря, я считаю ОО эдаким распиаренным костылём, с помощью которого можно делать сложным образом простые вещи.

Впрочем, повторюсь, я не претендую на глубокое понимание сути LISP.

Ritz
()
Ответ на: комментарий от Ritz

> Впрочем, повторюсь, я не претендую на глубокое понимание сути LISP.

Ну и слава богу, ибо его вообще нет ;)

archimag ★★★
()
Ответ на: комментарий от Ritz

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

Я даже придумал новый слоган для ньюлиспа: «newLISP: Welcome back to the stone age!».

dmitry_vk ★★★
()
Ответ на: комментарий от Ritz

>desctructing-bind.

(destructuring-bind (a b c &key x y) '(10 20 30 :y 40 :x 50) ;; тут a = 10, b = 20, c = 30, x = 50, y = 60 )

Даже спорить не буду.
Я готов изменить своё мнение, если, например, я увижу конкретный код, который на каком-нибудь старорежимном ЛИСП’е работает отлично, а на newLISP — работает через задницу.
на newLISP — работает через задницу

Спорить тут действительно не о чем.

dmitry_vk ★★★
()
Ответ на: комментарий от dmitry_vk

Понял теперь. В newLISP это bind.

(bind '((x 1) (y 2)))
; result: x = 1, y = 2

(set 'struct '((one "two") 3 (four (x y z))))
(set 'pattern '((A B) C (D E)))
(bind (unify pattern struct))

A → one
B → "two"
C → 3
D → four
E → (x y z)

Что касается «через задницу» — тут вопрос идеологический. Я вижу, что у нас в корне разные понятия слова «задница». На мой взгляд, «через задницу» — это изобретать велосипед средствами LISP.

Ritz
()
Ответ на: комментарий от Ritz

>На мой взгляд, «через задницу» — это изобретать велосипед средствами LISP

Что и происходит с вашим кодом. Я всего-то просил показать аналог двух классов и функции. А мне уже про SQL сказали и «списки - наше всё».

dmitry_vk ★★★
()
Ответ на: комментарий от dmitry_vk

Я вижу, мне не удалось объяснить свою позицию. Ладно, пусть так.

Я рад, что хотя бы обвинение в отсутствие desctucting-bind и прочих традиционных операторов с newLISP снято.

Ritz
()
Ответ на: комментарий от Ritz

>LISP

i'm going to become rich and famous after i invent a device that allows you to stab people in the face over the internet

Love5an
()
Ответ на: комментарий от Ritz

>прочих традиционных операторов с newLISP снято.

Вот, например, полный список традиционных операторов. Интересно посмотреть, какие аналоги им есть.
http://www.lispworks.com/documentation/HyperSpec/Body/03_ababa.htm

block
let*
return-from
catch
load-time-value
setq
eval-when
locally
symbol-macrolet
flet
macrolet
tagbody
function
multiple-value-call
the
go
multiple-value-prog1
throw
if
progn
unwind-protect
labels
progv
let
quote

Love5an
()
Ответ на: комментарий от Love5an

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

http://www.newlisp.org/downloads/newlisp_manual.html

Большая часть операторов даже называется точно так же.

Кстати, let* из TinyScheme меня в своё время взбесил чуть ли не до ударов по клавиатуре. На мой взгляд, крайне неудобно сделан.

Ritz
()

Создайте тред newLisp vs Common Lisp, не гадьте тут.

mv ★★★★★
()
Ответ на: комментарий от k_andy

Я согласен с mv. Предлагаю закончить здесь обсуждение отличий CL от newLISP.

Возвращаясь к теме F.A.Q.: всё же хотелось бы видеть там хотя бы упоминание о newLISP.

Ritz
()
Ответ на: комментарий от Ritz

>1. По тредам. Там есть два варианта, как раз недавно разбирались.

Это не треды, это процессы. Тредов под виндой нет. Не под виндой есть fork и spawn. Итого - для сложных хеловордов, не более.

yyk ★★★★★
()
17 июня 2010 г.
31 октября 2010 г.
20 июля 2011 г.
Ответ на: комментарий от elverion

В стандарте (начиная с r4rs) по этому поводу написано:

(and <test1> ...) library syntax

The test expressions are evaluated from left to right, and the value of the first expression that evaluates to a false value (see section 6.3.1) is returned. Any remaining expressions are not evaluated. If all the expressions evaluate to true values, the value of the last expression is returned. If there are no expressions then #t is returned.

так что да, есть. Тут and по сути не функция, а специальная форма со своей стратегией вычисления.

quasimoto ★★★★
()
1 сентября 2011 г.
Ответ на: комментарий от quasimoto

Если идея о FAQ ещё в силе, есть следующая вики: http://lisper.ru/wiki/

Что-то эта вики не является вики - я не могу её отредактировать.

Кстати, вопрос, есть ли нормальный и полный справочник по CL? Недавно потратил целых пять минут (с матюками), чтобы найти вещь,которая мне редко нужна - ввод шестнадцатиричных чисел.

На всякий случай, пишу сюда: в документации данные о вводе/выводе чисел ищут в следующих местах:

стандартный синтаксис #, смотрим x,o,b,r,

управление системой счисления при печати,

вывод format-ом в разных системах счисления ну, заодно уж и

вывод чисел с плавающей точкой format-ом

Примеры.

'(#xFF  ; 16-ричное
      #o11  ; 8-ричное
      #b11  ; двоичное
   )
получим
(255 9 3)

ввод числа с произвольной системой счисления до 36

#36rz
получим
35

вывод print-ом (

(let ((*print-base* 16) (*print-radix* t)) (print 255) 
   (values) ; для подавления вывода результата вычисления
   ) 
получим
#xFF 

вывод форматом

(format t "~x ~x ~b ~36R" 190 10 5/4 1301362083)
получим
BE A 101/100 LISPER

видимо, префикс (он нзывается radix) автоматически форматом вывести нельзя, но можно ведь просто включить его в форматную строку:

(format t "#x~x" 15)
получим
#xF

А не хочет ли администрация почистить тему от ненужной дискуссии?

den73 ★★★★★
()
Ответ на: комментарий от den73

Что-то эта вики не является вики - я не могу её отредактировать.

Там регистрация нужна.

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

Вот как раз - перевод строк в числа (это из http://cl-cookbook.sourceforge.net):

(mapcar #'read-from-string '("#xFF" "#o11" "#b11"))
;=> (255 9 3)

(mapcar #'(lambda (s) (parse-integer s :radix 16)) '("FF" "AA" "CC"))
;=> (255 170 204)

но про символьную запись чисел в разных СИ вроде нету - можно сюда написать.

quasimoto ★★★★
()
20 октября 2011 г.

Кстати

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

вопиющее 4.2

buddhist ★★★★★
()
28 января 2012 г.

LISP -> Scheme -> Racket

Есть книга по лиспу на русском, можно начать с неё и затем следовать по цепочке?

le_legioner ★★
()
Ответ на: LISP -> Scheme -> Racket от le_legioner

Есть книга по лиспу на русском, можно начать с неё и затем следовать по цепочке?

English -> LISP -> Scheme -> Racket

;; fixed

на русском ничего толкого нет, и никогда не будет.

gensym ★★
()
Ответ на: комментарий от gensym

если начать с английского, то выбор большой:

LISP (CL):
PCL, PAIP, Cltl2, Land of Lisp, LOL, A Gentle Introduction To Symbolic Computation, Common Lisp/ An Interactive Approach, On Lisp, Object Oriented Programming In Common Lisp, AMOP.

Scheme:
SICP, HTDP, LISP In Small Pieces.

gensym ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.