LINUX.ORG.RU

Common Lisp - заготовка для portable define-advice

 , , ,


1

2

Не совсем portable, но заметно расширяет возможности для SBCL и CCL и приводит их к общему знаменателю. Для остальных реализаций возможно не более одного «совета» на функцию и реализация не завязана на родные возможности реализаций, а просто перешибает defun.

https://bitbucket.org/budden/cl-advice

В CCL не просто можно вызвать предыдущую функцию (с помощью (:do-it)), но и подменить ей аргументы.

В SBCL можно найти определения самой функции и её «советов» с помощью SWANK.

Говоря холиварно, это позор, что в EMACS и в питоне декораторы есть, а в CL - нет. Уж лет 20, как пора было это исправить и вот я сделал к этому шаг наконец-то.

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

★★★★★

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

@baz 
@bar
def foo(): pass
вместо
def foo(): pass
foo = baz(bar(foo))
А в лиспе зачем?

Virtuos86 ★★★★★
()

Если я правильно понял из википедии, что это такое, то почему просто не

(defgeneric func (lal))
(defmethod func ((lal t)) (print 'hi))
(defmethod func :before ((lal t))
  (print 'been-here-before))

Пропиариться решил, ушлепок?

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

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

Во всяком случае, усомниться в нужности нельзя, поскольку оно есть в Lispworks, CCL, ACL и в EMACS. Нет только единства между реализациями в том, как оно сделано.

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

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

в Lispworks, CCL, ACL и в EMACS

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

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

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

Но обрати внимание, что ты сначала спрашивал, «зачем нужен», имея в виду «не нужен». А как только выяснилось, что он везде есть, а значит, нужен, ты стал писать о том, что его легко запилить. Т.е. ты свою точку зрения на ходу поменял, т.к. оказалось, что ты не в теме. Инвариантным осталось лишь желание объяснить мне, что я сделал что-то не то. Тебе это вообще-то мешает видеть реальность и ты всё ещё не в теме.

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

Давай-ка я сформулирую четко, что я имел в виду с самого начала.

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

Но в лиспе особенности синтаксиса, который представляет код в общем виде как списки, в которых первая форма является управляющей, психологического эффекта «вау, нам дали „сахарку“, айда его пихать по делу и нет», как в питоне, нет и не будет. А будет более-менее тривиальщина.

Говоря холиварно, это позор, что в EMACS и в питоне декораторы есть, а в CL - нет.

Но ведь кто хотел, тот сделал, список ты перечислил сам.

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

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

Но шизофреником всё же называл.

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

Каков был тогда твой мотив в тот момент, когда ты задавал мне этот вопрос? Ведь ответ тебя не интересовал, раз ты его проигнорировал.

И ты теперь пишешь, что мотив был именно такой: объяснить мне, что этого делать не нужно, т.к. это «тривиальщина». Т.е. ты внутри изначально был убеждён, что это «тривиальщина», и тебе было важнее это высказать, чем узнать, зачем на самом деле нужен defadvice.

А какой смысл мне с тобой разговаривать, если ты со мной не разговариваешь на самом деле, а только используешь мои реплики как повод, чтобы высказать своё мнение?

Вот тебе ещё подтверждение существования спроса на эту фичу

https://www.reddit.com/r/lisp/comments/4zopm5/defadvice_on_sbcl/

И подробно расписаны недостатки костыльных решений.

Но ведь кто хотел, тот сделал, список ты перечислил сам.

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

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

Но ведь кто хотел, тот сделал,

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

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

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

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

no-such-file ★★★★★
()
Ответ на: комментарий от anonymous

Пропиариться решил, ушлепок?

(defgeneric func (lal))
(defmethod func ((lal t)) (print 'hi))
(defmethod func :before ((lal t))
  (print 'been-here-before))
(defmethod func :before ((lal t))
  (print 'been-here-before-2))
;; WARNING: redefining FUNC :BEFORE (#<SB-PCL:SYSTEM-CLASS COMMON-LISP:T>) in DEFMETHOD

Что-то пошло не так, ушлепок?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Ага, лучше одну функцию по всему коду размазать, чтобы потом искать, что пошло не так? ОК, я учту, что у лиспопетушоков-теоретиков так принято

anonymous
()

Говоря холиварно, это позор, что в EMACS и в питоне декораторы есть, а в CL - нет. Уж лет 20, как пора было это исправить и вот я сделал к этому шаг наконец-то.

Ничего не понял. Какие отношение имеет advice к декоратору?

Декораторы — это вот:

@export
(defun foobar ()
  ...)

@eval-when-compile
(defun macro-util () ...)


И они давно [url=https://github.com/m2ym/cl-annot]есть[/url] в CL.
monk ★★★★★
()
Ответ на: комментарий от den73

Вот тут на Хабре я вижу, что можно:

Да, всё действительно так просто! decorator — просто синтаксический сахар для конструкций вида:

another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)

И сразу следующий вопрос тогда: а можно ли так в cl-annot?

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

а можно ли так в cl-annot

Так можно в CL:

(setf (symbol-function another_stand_alone_function) (my_shiny_new_decorator (symbol-function another_stand_alone_function)))

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

Вот тебе ещё подтверждение существования спроса на эту фичу

Там человек хочет странного: A use case: given a remote long-living image, and not having access to the source files, I would like to be able to recall the source of a given defun as it was defined in the original file.

Не очень понятно, зачем ему для этого defadvice (setf (get 'func 'source) '(source from the file)) достаточно.

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

Почему нельзя сделать так:

(defun recurse (flist f)
  (if (null flist) 
      f
      (lambda (args) 
        (apply (car flist) 
               (recurse (cdr flist) f) args) 
               args)))

(defun decorator (func)
  (lambda (old args)
    (let ((decorators
           (loop for x in (cdr (get func 'decorator)) 
                 collecting x)))
      (recurse decorators old)
      (lambda (args) (apply first-decorator old args) (args))

(defun install-advice (func advice &key (advice-name 'default))
  (let ((old-dn (symbol-function func))
    (if (get func 'decorator)
        (setf (getf (get func 'decorator) advice-name) advice)
        (setf (get func 'decorator) `(advice-name ,advice)
              (get func 'source) (symbol-function func)
              (symbol-function func) (lambda (&rest args) (apply (decorator func) old-fn args)))))
?

Будет переносимо в рамках ANSI CL.

P.S. Не тестировал.

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

У меня было сделано для одного совета в рамках ANSI CL, правда, он вроде ломался при переопределении функции defun-ом. Да и твой тоже сломается. Я не думаю, что можно сделать не-ломающийся, не трогая defun.

Люксовая версия, по идее, должна выдерживать переопределение совета с любым именем, а также переопределение самой функции (советы не должны отваливаться). Обладает ли этими свойствами SbCL и CCL - я пока не выяснял (если не обладает - придётся терпеть). В Lispworks совершенно точно можно переопределять осовеченную функцию defun-ом и советы не отвалятся.

Также команда find-source должна показывать место определения функции и места определения всех её советов.

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

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

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

В Lispworks совершенно точно можно переопределять осовеченную функцию defun-ом и советы не отвалятся.

А если функция определяется как (setf (symbol-function foo) (compose f g k)) ? Или считаем функциональное программирование табу?

В Lispworks совершенно точно можно переопределять осовеченную функцию defun-ом и советы не отвалятся.

Всегда можно доопределить, или переопределить defun.

Также команда find-source должна показывать место определения функции и места определения всех её советов.

В стандарте ANSI такой функции нет.

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

В принципе я про то, чтобы твой cl-defadvice для ANSI CL не ломал API. А то на clisp, например, даже те тесты, которые в нём самом, не проходят.

А для остальных - наколеночный, ломающийся при переопределении функции.

Вот именно поэтому я не люблю использовать Common Lisp. 90% внешних библиотек и, как недавно выяснилось (тобой) и SBCL работают именно по этому принципу.

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

Всегда можно доопределить, или переопределить defun.

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

В стандарте ANSI такой функции нет.

А в среде разработки есть и она нужна.

А то на clisp, например, даже те тесты, которые в нём самом, не проходят.

Ты проверил, что ли? Спасибо! Да, не должны работать, т.к. они проверяют множественные советы, а их нет. Нужно тесты поменять.

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

90% внешних библиотек и, как недавно выяснилось (тобой) и SBCL работают именно по этому принципу.

Ну здесь можно подойти с двух сторон:

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

А если функция определяется как (setf (symbol-function foo) (compose f g k)) ?

В этом случае find-source не найдёт определение foo.

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

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

Можно. Делаешь свой пакет myCL, в нём переопределяешь всё, что надо, реэкспортируешь оставшееся и используешь вместо CL.

Нужно тесты поменять.

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

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

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

Да я про другое. Если что-то делаешь, надо делать это хорошо. Причём даже в классическом Лиспе этот принцип до недавнего времени соблюдался. Более того, именно этим Лисп (и лисп-машины) противопоставлялся тогдашнему Си (и Юниксу).

В этом случае find-source не найдёт определение foo.

Опять «работает в 90% случаев»...

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

Вот я сейчас занимаюсь тем, что патчу реализацию CL. Эта функция

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

2. определена до того, как я имел возможность поменять defun.

Её твоим способом не поменять. А надо сказать, что большинство моих патчей модифицируют swank, asdf или саму реализацию. Так что отсутствие в реализации родного defadvice ничем не компенсируется.

Опять «работает в 90% случаев»...

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

Если что-то делаешь, надо делать это хорошо.

Я понимаю. Я недоделал Portable defadvice, поэтому мой проект называется «an attempt», может быть лучше было бы назвать «prototype». Но я сделал определённую часть работы, а именно, запись определения для SBCL и возможность подмены параметров для CCL. Если кому-то ещё нужен portable defadvice, то нетрудно допилить. А у меня нет на это временных ресурсов. Хотя, может быть, я всё же потрачу время сегодня на твой код и на тесты в CLISP. Как пойдёт.

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

Причём даже в классическом Лиспе этот принцип до недавнего времени соблюдался.

Даже нашёл момент, когда всё испортилось. Когда пошёл переход от разработки в образе к разработке через пересборку. Половина механизмов Common Lisp с этим несовместима (defconstant, defpackage, (setf (symbol-function foo) (f (symbol-function foo))), изменение синтаксиса, ...), другая половина недостаточна (find-source сделать правильно невозможно, интегрировать отладчик правильно невозможно, инкрементальную сборку сделать правильно невозможно, ...).

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

А что там нельзя сделать декоратор для функции?

Можно. Но декорированная функция должна иметь другое имя.

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

Но декорированная функция должна иметь другое имя

И в питоне тоже. Это не значит, что нельзя использовать косвенный вызов функции. Собственно так везде и делается.

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

Я недоделал Portable defadvice, поэтому мой проект называется «an attempt», может быть лучше было бы назвать «prototype».

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

1. Унификация API к механизмам аналогичным advice

2. Частичная реализация переносимого advice.

Это всё равно, что вместо closer-mop и pcl был бы один проект. Раздели задачи. И сделай унификационную часть более единообразной. Посмотри на swank. Чтобы добавление очередной реализации можно было сделать просто добавлением файла.

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

Это не значит, что нельзя использовать косвенный вызов функции. Собственно так везде и делается.

Это значит, что по имени функции можно однозначно получить точку её описания. В отличие от функций Лиспа и методов ООП.

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

Это значит, что по имени функции можно однозначно получить точку её описания

По имени да, но декорированная функция вызывается не по имени, а по указателю/ссылке.

В отличие от функций Лиспа и методов ООП

ООП не является такой уж редкостью в Си. Во всяком случае на уровне «структура с полями-указателями на функции».

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

А если функция определяется как (setf (symbol-function foo) (compose f g k)) ? Или считаем функциональное программирование табу?

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

На самом деле вообще эта фича (advice) не кажется такой уж суперполезной. В тех случаях когда действительно необходимо, можно заранее предусмотреть возможность навешивания middleware в виде списка, т.е соорудить специальный объект и методы к нему. Прикручивать же такую возможность ко всем функциям вообще - ИМХО это оверкилл.

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

Когда пошёл переход от разработки в образе к разработке через пересборку.

Наверное, ты отчасти прав. Но только отчасти. defconstant противоречит идее динамического языка как таковая, независимо от способа пересборки. Проблема find-source вызвана тем, что чтение настраиваемое, не функционально чистое и при этом API для интроспекции чтения недостаточен, чтобы с этим справиться. Проблемы отладчика связаны с не функционально чистыми макросами, но такие макросы нужны (та же проверка SQL запросов во время компиляции).

Разработка через пересборку в целом лучше, чем разработка в образе, поскольку она позволяет держать вещи под контролем. Должен быть акт рождения новой сущности. Можно сравнить с живыми организмами. Мать необходима для того, чтобы ребёнок родился, но в целом ребёнок определяется своей ДНК, поэтому баги в образе матери можно исправить путём рождения следующего поколения. Может быть, есть методики, как того же добиться и при разработке в образе. По сути, все нормальные лиспы примерно так размножаются. В случае SBCL я рассматривал этот вопрос более-менее подробно (см. sanely bootstrappable common lisp, в CCL, как я понял, менее чётко, но пока его не пробовал пересобирать.

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

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

Раздели задачи. И сделай унификационную часть более единообразной.

Я бы рад. Я написал в openmcl-devel и в sbcl-devel. Никто не отреагировал. Значит, это никому не нужно. У меня нет времени делать то, что никому не нужно. Моя конкретная задача сейчас - переехать с SBCL на CCL и я уже сделал то, что нужно в её рамках. Я потратил целый день на эту библиотеку - уже слишком много. В т.ч. я переименовал сущности - зачем, спрашивается, я старался и вносил в свои логи контроля версий гигантские коммиты на десятки файлов?

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

На самом деле вообще эта фича (advice) не кажется такой уж суперполезной.

Пойми одну простую вещь: CL умирает. Он сам по себе «не кажется таким уж суперполезным». Вот antares0 соловьём разливался про «сообщество». А на самом деле завтра обанкротятся те, кто спонсирует развитие SBCL, и SBCL резко не станет. CCL де факто мёртв. Посмотри на дату выхода последних версий SBCL по платформам - он уже отчасти умер. И, что ещё важнее, сравни даты выхода последних стандартов COBOL, C, Fortran и CL.

Вот Monk ушёл на Racket, многие ушли на Rust, Golang, Python. Там есть развитие. А CL отстаёт. Раз ты в этой теме, тебе, наверное, нравится CL. Смени свой образ мысли и откажись от элитности. Нет уже никакой элитности. Нужно думать, как спасать язык, чем его расширить. И нет, это не библиотеки. Нужно улучшать инструменты и расширять сам язык, иначе он умрёт. И не нужно ждать, пока это сделает ANSI - это нужно делать силами сообщества. Я это понял ещё лет 7 назад, но остальным это по барабану, да и вообще лисперов становится меньше и меньше.

Далее, я тебе могу легко обосновать, зачем нужен defadvice для любых функций: для юнит-тестов. Есть технологии mocking и faking, они как раз делаются через defadvice.

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

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

Не согласен. Получился один проект, просто его возможности зависят от реализации CL. учитывая, что inline функции всё равно нельзя просоветовать надёжным образом, этот механизм всегда будет отчасти ущербным.

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

Пойми одну простую вещь: CL умирает. Он сам по себе «не кажется таким уж суперполезным».

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

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

Есть ощущение того, что использование языка очень ограничено и, практически невозможно найти на нем работу.

Мне и ASDF кажется достаточно неудобным, но, может быть, я не прав.

Мне очень нравятся идеи, что заложены в CL, как и, вообще, в лиспе как таковом.

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

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

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

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

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

как спасать язык, чем его расширить. И нет, это не библиотеки

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

сравни даты выхода последних стандартов COBOL, C, Fortran и CL.

И что? Все эти коболы и фортраны это вещи в себе, я уже как-то говорил, что я об этом думаю - они в живой природе не встречаются. CL проигрывает в это смысле только потому, что нет такой кучи легаси на нём, а что есть проще переписать на крестах/джаве, чем изобретать новые стандарты для соответствия современным реалиям. Тем более что все эти «новые стандарты» по фичам сосут даже у довольно древних лиспов.

Впрочем на счёт стандартов, я отчасти согласен - нужно развивать стандарты _реализаций_ конкретных фич. Например асинхронщина - нет единого способа реализации (интерфейса), в итоге имеются кучка библиотек под разные libev/uv с разным интерфейсом. Каждый пилит свой велосипед, и ни одной нормальной библиотеки нет, сплошные PoC с «обработать напильником». Т.е. ИМХО нужно уходить от единого монолитного стандарта языка в сторону наборов стандартов, вроде пыховских PSR, или скимовских SRFI.

Есть технологии mocking и faking, они как раз делаются через defadvice

Во всём остальном мире они почему-то прекрасно делаются и без defadvice.

многие ушли на Rust, Golang, Python. Там есть развитие

Там есть деньги. А кушать как-то очень хочется. И да там есть развитие, но не развитие языков, а личное развитие, потому что там есть крутые проекты, где можно многому научиться.

могу легко обосновать, зачем нужен defadvice для любых функций

Я могу предположить, что в системе a la emacs адвайсы полезны для любых _пользовательских_ функций. Но это не требует какого-то нового стандарта языка, т.к. достаточно реализовать особые advisable функции-команды, оставив при этом в покое обычные bare-функции. И да для такой _реализации_ (в смысле интерфейса) неплохо было бы иметь стандарт, чтобы разные библиотеки могли быть взаимозаменяемы.

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

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

При разработке в образе проблемы нет. Если действительно константу надо поменять, то есть unintern. А от случайного изменения она правильно защищает. А вот когда у тебя есть «перезагрузить файл/перезагрузить пакет», то всё грустно.

Проблема find-source вызвана тем, что чтение настраиваемое, не функционально чистое и при этом API для интроспекции чтения недостаточен, чтобы с этим справиться.

А ещё тем, что в образе может остаться функция, которую уже удалили из файла. И тем, что функция может быть создана из REPL.

Проблемы отладчика связаны с не функционально чистыми макросами

Я больше про то, что ANSI CL предполагает текстовый отладчик в терминале. А IDE предполагает нормальный API к состоянию остановленного процесса.

А сейчас ты скажешь, что в Racket-е всё это решено :)

Разумеется. Точнее решено было в Scheme. Поэтому её и называли Алгол со скобками.

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

Например асинхронщина

Например, адвайсы.

Во всём остальном мире они почему-то прекрасно делаются и без defadvice.

Слушай, ну я не настолько в теме, всего один квартал на CL их писал, в т.ч. мне довелось видеть библиотеку для создания defadvice-ов переносимо между реализациями CL, и присутствовал на совещаниях, где были люди из мира Java и C++. Я не особо следил за тем, что у них происходит, но почему-то картины счастья у меня не нарисовалось. Думается, делаются так же, с помощью всякого рода костылей. «Нормальные» языки обычно имеют всякие ограничения доступа, типа private или final, поэтому писать юнит-тесты - задача не вполне тривиальная всегда. Чисто ИМХО.

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

Тебе не кажется странным, что бабло на издание новых стандартов кобола и фортрана при этом всё же нашлись?

И да там есть развитие, но не развитие языков,

Ты сам-то веришь тому, что написал?

Нда, давненько у нас не было лиспосрачей. Впрочем, это тоже симптом. Нет лисперов - нет и лиспосрачей. Я пас.

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

А ещё тем, что в образе может остаться функция, которую уже удалили из файла. И тем, что функция может быть создана из REPL.

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

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

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

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

В качестве примера можно взять hu.dwim (правильная стандартная библиотека), xcvb (правильная пакетная система), мой advanced readtable. Количество пользователей пренебрежимо мало даже по сравнению с количеством пользователей SBCL. Потому что каждый считает, что правилен именно его путь изменения стандарта.

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

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

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

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

Например, адвайсы.

Как я уже сказал - в виде специальных advisable-функций, вполне годится. Как фичу языка - ненужно. Асинхронщина как фича языка - тоже ненужно.

что бабло на издание новых стандартов кобола и фортрана при этом всё же нашлись?

Ну жить в 21 веке без ООП и т.п. фич и пилить новый код было совсем уж тяжко, пришлось таки написать. Это не результат действий какого-то сообщества, а превентивные меры, предпринимаемые корпорациями для удержания клиентов.

Ты сам-то веришь тому, что написал?

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

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

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

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

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