LINUX.ORG.RU

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

В чём? В том, что на лиспе код пишется быстрей, чем на C и C++?

пилшите, Шура, пилшите - рабочий код (не абстрактный, а на github или даже в репах) лучший аргумент, гораздо лучше однообразных рассказов от одних и тех же персонажей о крутости лиспа из года в год

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

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

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

элементы программирования.

вот несколько минут(23мин00 - 28мин): http://www.youtube.com/watch?feature=player_detailpage&v=ptqzhxGPGy0#t=1380s

либо 1580s - конкретно про символьные манипуляции

либо 1659s - конкретно по проектирование софта

либо (слайд с евклидом) - конкретно замещение Александреску лист.

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

В том, что лисп имеет какие-либо преимущества перед мейнстримом, куда бидон таки относится.

5-6 лет назад не относился, например. А сейчас clojure весьма-так набирает популярность, а ты - предубежден.

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

тут скорее конформизм и движение в потоке и нонконформизм и возможно синдром «я не такой как все»

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

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

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

И с чувством глубокого удовлетворения идти домой, где уже ждёт тарелочка аппетитного мамкиного борща.

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

А какие языки «ненормальны»?

Да что, мало ли что ли уродливых языков? Java, JS, похапэ, 1С, pascal, тыщиих, уродцев.

Для разных задач нужно разное. Я и С++ использую, например. Плохой язык?

Для определенного круга задач - незаменимый, плохозаменимый.

Просто для некоторых задач есть более подходящие инструменты.

Ну вот для некоторых лисп вполне себе торт.

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

Ну так я в Java подсуну свой classloader - изменится поведение оператора new.

Это изменение рантайма. Рантайм в CL не стандартизован, но всё равно примечательно, как в компилятор SBCL добавили поддержку SSE2: загружалась библиотека, определявшая новые VOP'ы и трансформации.

Навешу аннотацию - изменится поведение сеттера.

Стандартная часть языка (привет CLOS, кстати).

Переопределю методы интерфейса Iterator - изменится поведение конструкции for. И?

А можно переопределить поведение class? Или вот пусть тот же new, но чтобы он к classloader'у не ходил?

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

Не, на clojure посматриваю. Но сейчас я достаточно, в принципе, активно начал применять scala(хотя еще в процессе изучения), не знаю, будет ли смысл использовать clojure. Ради STM? Насколько там это полноценно и круто сделано? В scala вроде мусолится вопрос по включению библиотеки с реализацией STM в стандартную. Или ради макросов? Так в scala тоже ввели недавно(пока не изучал подробно).

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

Это изменение рантайма.

И? Поведение элемента языка изменилось.

А можно переопределить поведение class?

А можно себе анус дёрнуть левой ногой через правое плечо?

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

пилшите, Шура, пилшите - рабочий код (не абстрактный, а на github или даже в репах) лучший аргумент, гораздо лучше однообразных рассказов от одних и тех же персонажей о крутости лиспа из года в год

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

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

Конструктор копий должен быть один

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

struct Tree { обычное дерево };
template <class CopyStrategy> struct TreeWithSomeCopy {}; // параметрический тип ограничивающий наследников
template <> TreeWithSomeCopy<Shallow> : public Tree { тут обычный конструктор копирования };
template <> TreeWithSomeCopy<Deep> : public Tree { тут глубокий };

// если теперь есть
template <class CopyStrategy> void f(TreeWithSomeCopy<CopyStrategy> tree) { можно использовать tree как обычное Tree }

Tree tr = ...; // и какое-то обычное дерево
f(static_cast<TreeWithSomeCopy<Shallow>&>(tr)); // то тут в f скопируется поверхностно
f(static_cast<TreeWithSomeCopy<Deep>&>(tr)); // а тут -- полностью

Хочешь разные - делай методы

Я так и сказал выше, что «проще сделать нормальные методы и выбор в месте вызова», то был пример про стратегии.

struct Tree {
    ...
    Tree clone_shallow(); // RVO
    Tree *clone_deep(); // new
};

явно проще, просто ТС хочет передачу с (произвольным?) копирование в функцию без явного вызова (какого-либо) copy, как в С++ для не ссылок и указателей.

Ну и стратегии могут быть более расширяемыми (можно дописать ещё наследников в рамках TreeWithSomeCopy).

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

Изучайте: https://github.com/languages/Common Lisp

И? Это же просто кучки говнокода, высранные лисп-адептами. Ты нам промышленный код покажи, хотя бы уровня JBoss или WebSphere.

Common Lisp is the #33 most popular language on GitHub

Лол. Впереди планеты всей.

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

И? Поведение элемента языка изменилось.

Да, собстсвенно, нет: класслоадер как вызывался, так и вызывается.

А можно себе анус дёрнуть левой ногой через правое плечо?

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

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

Это же просто кучки говнокода, высранные лисп-адептами.

Вы телепат и анализируете его даже не просматривая?

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

либо 2813s (46:53) - конкретно замещение Александреску лист.

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

Не, на clojure посматриваю. Но сейчас я достаточно, в принципе, активно начал применять scala(хотя еще в процессе изучения), не знаю, будет ли смысл использовать clojure. Ради STM?

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

Насколько там это полноценно и круто сделано?

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

Или ради макросов? Так в scala тоже ввели недавно(пока не изучал подробно).

Макросы в языках с духовн^W богатым синтаксисом хоть и возможны (scala, nemerle итд), но *на_практике* вставляют значительно больше палок в колеса, чем языки с однородным и простеньким синтаксисом (почти отсутствующим - этисамые лиспы). Если бы я программил под jvm, упаси-бох, то склонялся бы к использованию именно скалы, хотя со стороны она выглядит монстриком: java (ооп, синтаксис) + haskell (структуры данных, функциональщина) + lisp (макросы) + perl (избыточный синтаксис, всякие встроенные в язык парсилки xml и тому подобное). Симпатичный такой... монстр :)

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

Мне в личное время неохота уже ничего писать. Программирование - это банально и скучно

Это ты просто не нашел интересную точку приложения. Запили язык, фреймворк, стартап.

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

все - лисп ради лиспа?

На каком основании делается такой вывод? Большинство приличных библиотек написаны исходя из реальных потребностей. Когда пишут в стиле «лисп ради лиспа» получается обычно фигня (это справедливо и для других языков). Там есть несколько форков Maxima. Есть StumpWM.

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

На каком основании делается такой вывод?

на кол-ве и качестве «конечных продуктов», которые я считаю разумной целью разработки

Большинство приличных библиотек написаны исходя из реальных потребностей

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

Там есть несколько форков Maxima. Есть StumpWM.

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

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

я пока выберу другие - доступные и лучшие

Я думаю это замечательно, что у вас есть выбор.

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

Какие есть на github сопоставимые (с приведённым списком) продукты на node.js?

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

Я думаю это замечательно, что у вас есть выбор.

однозначно

Какие есть на github сопоставимые (с приведённым списком) продукты на node.js?

а причем тут node.js? типа еще менее нужная вещь? не буду спорить, а вот в doom3, например, я вполне себе играл, он есть на github, diaspora там есть, если говорить про web, redis, linux (ядро), textmate и многие другие проекты, которые готовы к использованию

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от anonymous

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

Пролог (facts, rules, unification, backward chaining) успешно встраивается в Common Lisp. Это есть в основных коммерческих реализациях LispWorks и Allegro CL. Встраиваемый пролог - одна из продающихся фишек LispWorks (у него их несколько наряду с CAPI - библиотекой GUI и графикой).

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

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

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

Объективно, надо сравнивать с python, ruby, scala...

Могу описать свой небольшой опыт и сравнить разработку на Scala и Common Lisp.

В целом скорость разработки примерно одинаковая. Код на Scala короче, но у него и выше смысловая нагрузка, т.е. его чуточку тяжелее читать, с ним немного тяжелее работать. Код на лиспе многословнее (из-за динамической типизации), но от силы в раза 1,5 - 2 по сравнению со Scala. Концептуальная нагрузка на код примерно такая же.

Макросы могут изменить ситуацию. Если есть место для rule-based programming (паттерн-матчинг какой, но необязательно в смысле Scala, или какие декларативные правила, которые надо скомпилировать в развесистую лапшу кода), то код на лиспе может стать короче и лаконичнее, чем на Scala.

Код на Scala обычно легко переписывается в эквивалентный код на лиспе. Например, линеаризация списка наследования появилась в лиспе задолго до Scala. Это не изобретение Мартина Одерского. Тут особых проблем нет.

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 2)
Ответ на: комментарий от Alex-Alex

Во первых непонятно, как в лиспе тогда пишут в функциональном стиле, когда все объекты CLOS передаются по ссылке

В ФП все объекты - неизменяемые, так что пофиг.

И как решить такую задачу: передать в функцию копию произвольного объекта, изменить несколько слотов и вернуть этот объект

Это не ФП. В ФП вы делаете новый объект с новыми полями.

no-such-file ★★★★★
()
Ответ на: комментарий от Alex-Alex
(defgeneric gen-copy (obj strategy)
  (:documentation "OBJ -- object, STRATEGY -- symbol, kind of copy"))

(defmethod gen-copy ((obj standard-object) strategy)
  (let* ((class (class-of object))
    (copy (make-uninitialized-instance class)))
    (dolist (slot (copy-class-slots class))
      (let ((slot-name (slot-definition-name slot)))
        (when (slot-boundp object slot-name)
          (setf (slot-value copy slot-name)
          (slot-value object slot-name)))))

(defmethod gen-copy ((obj cons) strategy)
  (cons (car obj) (cdr obj)))

(defmethod gen-copy ((obj cons) (strategy (eql :list))
  (copy-list obj))

(defmethod gen-copy ((obj cons) (strategy (eql :tree))
  (copy-tree obj))

(defmethod gen-copy ((obj sequence) strategy)
  (copy-sequence obj))

(defmethod gen-copy (obj strategy)
  "Default method"
  obj)


(defun copy (obj)
  (gen-copy obj nil))

Вот и всё. Для любого объекта созданного через defclass работает ровно как в C++. Для структур надо будет доопределять gen-copy (или сделать defstruct+ которые будет делать это автоматически).

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

Есть рационализаторское предложение :)

Можно добавить глубокое копирование как часть стратегии. Да, вообще, рассматривать стратегию как множество ключевых слов, а не один символ.

P.S. Табами пользуешься?

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

Можно добавить глубокое копирование как часть стратегии.

Можно. Затем и есть аргумент strategy. (defmethod gen-copy ((obj standard-object) (strategy :deep)) ...)

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

P.S. Табами пользуешься?

Пользуюсь. Но в лоровском текстовом поле они не работают, а этот код я писал сразу в нём.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от Alex-Alex

Есть еще вопрос, как экспортировать из пакета символы всех акцессоров класса?

Простой путь:

(use-package :hu.dwim.def)

(def (class ea) my-class
   ....)

А если напишешь (class eas), то ещё и все поля экспортируются.

Сложный путь: можно написать экспортилку всего, что является дженериком и имеет первый параметр нужного типа через cl:do-symbols и анализ каждого символа в пакете.

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

Да, вообще, рассматривать стратегию как множество ключевых слов

Тогда придётся свой диспатчер писать. EQL не умеет «множество».

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

Если экспорты будут разбросаны по коду, то это затруднит его чтение и понимание.

Вообще-то в чём проблема сделать

(let (l) 
  (do-external-symbols (i package-name) 
    (push i l)) 
  (sort l (lambda (x y) 
            (string< (symbol-name x) (symbol-name y)))))
?

И получишь сразу весь список внешних символов. А когда у тебя в тексте стоит (external 'foo) (defun foo ...) хотя бы сразу видно, что этот символ внешний, а не надо рядом в defpackage его искать.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

надо отслеживать кольцевые зависимости

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

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

Но это вводить свой метакласс, хотя почему бы и нет?

Вот-вот. В 95% случаев достаточно shallow-copy как в C++. А для остальных 5% проще писать стратегии :list :tree, :contained, :recurse-contained, :container, :deep .... и.т.д

К слову, проблема кольцевых ссылок не фатальна: в cl-store, например, просто создается хэш (старый->новый) куда по мере копирования заносятся объекты.

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

Для структур надо будет доопределять gen-copy (или сделать defstruct+ которые будет делать это автоматически).

Намекну немножко:

(defstruct foo x y z)
; FOO

(class-of (find-class 'foo))
; #<STANDARD-CLASS STRUCTURE-CLASS>

(class-slots (find-class 'foo))
; (#<STRUCTURE-EFFECTIVE-SLOT-DEFINITION for instance slot X #x302000E3143D> #<STRUCTURE-EFFECTIVE-SLOT-DEFINITION for instance slot Y #x302000E30EBD> #<STRUCTURE-EFFECTIVE-SLOT-DEFINITION for instance slot Z #x302000E30DED>)
korvin_ ★★★★★
()
Последнее исправление: korvin_ (всего исправлений: 1)
Ответ на: комментарий от monk

К слову, проблема кольцевых ссылок не фатальна: в cl-store, например, просто создается хэш (старый->новый) куда по мере копирования заносятся объекты.

Ну, этот алгоритм очевиден.

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

А разве это ANSI-совместимо?

Что именно? class-slots в стандарте нет, но она есть, вероятно, во всех реализациях, однако copy-class-slots из твоего примера в HyperSpec тоже не упоминается. А соотношение классов и типов (в т.ч. структур) упоминается: http://www.lispworks.com/documentation/HyperSpec/Body/04_cg.htm

И вот еще: http://www.lispworks.com/documentation/HyperSpec/Body/t_stu_ob.htm

korvin_ ★★★★★
()
Последнее исправление: korvin_ (всего исправлений: 1)
Ответ на: комментарий от anonymous

Он и в С++ встраивается. Не переставая от этого быть прологом.

Не видел, но предполагаю, что нет той степени интеграции, что существует между лиспом и прологом.

Прологовское правило - это обычный список лиспа (s-exp). Такие правила можно порождать макросами, например, при преобразовании грамматических правил в прологовские. Результатом унификации тоже являются обычные s-exp, представляющие термы, что удобно для обработки результатов. Более того, примитивы пролога можно задавать напрямую в виде обычных функций самого лиспа (есть соглашение о наименовании), вызывая унификацию и движок самого пролога вручную по мере необходимости. Ввод нового правила - это по сути всего одна форма лиспа (читай, всего один statement в Си++). Запрос - другая форма. Все коротко и ясно.

Конечно, хорошо, что пролог тоже можно встраивать в Си++.

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

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

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

Да там quasimoto в начале ссылку приводил. Можно оттуда взять. (не проверял такие детали)

Пропустил, жаль нельзя сообщение треда отфильтровать по автору. Или можно?

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

Во первых непонятно, как в лиспе тогда пишут в функциональном стиле, когда все объекты CLOS передаются по ссылке.

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

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

Во-первых, не пишут.

Пишут. https://github.com/fare/lisp-interface-library/tree/master/pure

для функционального стиля глубоко пофигу, по ссылке оно, или по значению.

Если бы было по значению, то в функциональном стиле работало бы очень медленно (вызов функции = копирование, общие данные делать нельзя, ужас в общем).

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

Вот как раз с явой у меня не сложилось. Три раза качал rpm с сайта Oracle, они не завелись. Ладно. Пытался запустить Эклипс, он грузился 40 минут на ноутбуке. Я не дождался и снес его нафик.

Alex-Alex
() автор топика
Ответ на: комментарий от anonymous

Конструктор копий должен быть один

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

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