LINUX.ORG.RU

В чём плюсы image-based разработки?

 , ,


2

13

archimag сказал, что image-based разработка — для него основное достоинство Common Lisp. В варианте SLIME. То есть не формируем в конце исходники из образа, а меняем исходники и на каждом шагу чуть-чуть меняем образ.

Имхо, image-based заставляет смотреть на программу не как на результат компиляции файлов исходников, а как на живой REPL, который иногда можно подкрутить для получения результата.

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

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

★★★★★

Последнее исправление: monk (всего исправлений: 3)

В чём плюсы image-based разработки?

Для меня это интерактивная разработка.

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

Еще удобна восходящая разработка с использованием REPL, например, при создании чего-то нового. Тоже время сокращает. Особенно хорошо получается, если код получается функционально чистым в лучших традициях ФП - тогда его легче отлаживать. Тоже вполне интерактивно, когда попеременно переключаешься между REPL и редактором.

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

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

dave ★★★★★
()

Каникулы. Дни лиспа на ЛОРе.

anonymous
()

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

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

Вот как у меня щас: два раза конпеляцию с деплойментом прогнал за день, всё, пора домой. И то, подзадержался.

Опа, спрыгнул с С-интерпрайза?

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

Чем жирнее проект, тем быстрее скорость разработки в image-based среде. Фактически, перекомпилировать/перезапускать всё нужно, когда образ foobar (fucked up beyond all repair) оказался.

А что вообще подразумевается под «образом»? Если состояние интерпретатора - то он есть в любом ЯП с реплом. Если возможность скинуть состояние в файл - это просто не нужно, даже вредно.

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

Опа, спрыгнул с С-интерпрайза?

Нет, это про него. 2.5 часа собирается, 1.5 деплоится.

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

А что вообще подразумевается под «образом»?

Процесс (память + состояние).

Если состояние интерпретатора - то он есть в любом ЯП с реплом. Если возможность скинуть состояние в файл - это просто не нужно, даже вредно.

Это, считай, как core dump, только живой.

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

лисп тут совсем не уникален.

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

Точнее не так. Нет _удобной_ возможности. Просто подменять функции на ходу можно в erlang. Причём отсутствие явных циклов (только tail-recursive) позволяет менять выполняемую функцию. Закачал, применил, со следующей итерации уже новая версия. Можно в Java через classloader. Можно в том же Racket, если это функция текущего модуля.

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

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

Можно в том же Racket, если это функция текущего модуля.

В Racket можно все так же как в CL, только надо сделать (enforce-module-constants #f). Гейзер так и работает.

Но вот исправить функцию в файле, ткнуть «перекомпилировать функцию» и не быть обязанным _перезапускать_ REPL

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

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

Гейзер так и работает.

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

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

По-моему, ты смешал image и «live REPL». Насколько я понял, по крайней мере ракетчики разделяют эти понятия.

Не только я один, но в lispworks тоже «смешали».

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 1)

Кроме того, что image-based хреново работает со стандартными средствами командной строки — ничего.

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

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

Приведи подробный пример для Scala, пожалуйста. Что ты имеешь в виду под этим?

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

Автор делит языки программирования на «живые»

Интересно, кому-нибудь нужна живая стиральная машина?

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

кому-нибудь нужна живая стиральная машина

На linux.org.ru всем нужна _свободная_ стиральная машина :-) Пусть будет мёртвая, но свободная!

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

Пусть будет мёртвая, но свободная!

Надо положить на неё учебник по квантовой механике. Information would set you free!

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

Information would set you free!

Arbeit macht frei!

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

Да. Но я не могу придумать для него ни одного юзйейса, так что нет - и не надо.

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

Гейзер не умеет перекомпилировать в точке останова.

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

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

Приведи подробный пример для Scala, пожалуйста. Что ты имеешь в виду под этим?

Пишем в репле определение функции, потом пишем новое определение функции. Все работает же?

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

Даже в статически-типизированных типа хаскеля ...

Тут же говорят про ф-ию, или есть способ? А то ведь ":load" _для модуля_ (1). А важнее, что _состояние repl нарушается_ (2): let - привязки теряются.

Но может есть другая команда / альтернатива ghci?

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

На игрушечных проектах... Этого мало.

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

Все работает же?

Сам по себе REPL (scala(1)) в смысле пригодности для monkey patchingа там не работает. Например:

scala> def a = 1
a: Int

scala> def b = a + 2
b: Int

scala> a
res0: Int = 1

scala> b
res1: Int = 3

scala> def a = 2
a: Int

scala> a
res2: Int = 2

scala> b
res3: Int = 3

аналогично если раскидать по файлам object A { def a = 1 } и object B { def b = A.a + 2 } — :load обновлённого A никак не влияет на зависящий от A объект B (есть правда хохма в виде :replay).

То есть как GHCi он себя ведёт.

В SBT для этих целей есть свой REPL — там изменения подхватываются автоматически и всё зависящее их учитывает. Но всё равно неудобно и монструозно по сравнению с CL (там изначально никаких проблем, так как символы).

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

В ruby, lua, node кажется можно. В R тоже должно. Про perl и php не уверен, но python точно нет.

ados ★★★★★
()

1) такой способ разработки _очень_ быстр. пока не попробуешь не убедишься насколько это важно для самочувствия разработчика :)

2) для R он вообще основной режим. в режим, когда «реален исходный код а не объекты в репл», переключаются только когда нужно переключится на литературное программирование, или работа очень объемная и длительная.

а в чем проблема то? ведь лисп программа распространяется все равно в виде образа системы?

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

ведь лисп программа распространяется все равно в виде образа системы?

Ну если это самодостаточная программа (типа бинарник), то да. А так git/asdf-install/common-lisp.net

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

ведь лисп программа распространяется все равно в виде образа системы?

Кстати, ещё один интересный момент. Используем библиотеки под GPL. Сделали образ путем где-то компиляции функций, где-то подгонкой в REPL. Что теперь является исходником для получившегося образа? Из исходного кода его получить без ручной подгонки невозможно.

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

А так git/asdf-install/common-lisp.net

Из которых потом создается в памяти «running image» после компиляции кода... Точнее, этот код компилируется в текущий «running image», изменяя последний.

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

не имеешь права, т.к. его невозможно собрать из исходников

Хм. То есть нельзя накладывать бинарные патчи на GPL программы? А GTK3 под windows распространять можно? Насколько я помню, билдскриптов под неё не существует.

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

в принципе он сам себе программа, причем как я понимаю все функции в нем разворачиваются в исходный их текст? :)

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

Исходники + список ручных действий. То бишь исходники в наболее пригодной форме.

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

причем как я понимаю все функции в нем разворачиваются в исходный их текст? :)

Нет как повезет. Для CL в общем случае этого не обещали.

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

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

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

Если она высонагруженная, то скорее всего на многих машинах?

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

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

Тогда будем руками ковыряться?

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

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

подгонкой в REPL

Зачем? Не делайте так и ваши волосы будут мягкими и шелковистымине будет проблем.

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

Как поможет эта утилита, если поменялся тип и нужно изменить логику. Была map стала list, что тут перекомпилировать? Из-за динамической типизации есть еще более высокая вероятность что ошибка проскочит как-то

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

Была map стала list, что тут перекомпилировать?

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

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

В результате тестовые случаи, проверяемые в REPL зачастую невоспроизводимы

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

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

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

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

В статически типизированном да, но в лиспе хоть и есть такие возможности, но их мало используют. И у тебя список полетит в функции обработки map

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.