Какие особенности языка программирования хорошо подходят для разработки живой системы кодирования?
Я хотел бы создать "живую кодировку".
Я должен объяснить, что подразумевается под "картой живой кодировки". Я сделаю это, сравнив живое кодирование с традиционным кодированием.
В общем случае, в традиционном программировании вы пишете код, иногда компилируете его, затем запускаете исполняемый файл или открываете script в каком-то интерпретаторе. Если вы хотите изменить свое приложение, вы должны повторить этот процесс. Живая система кодирования позволяет обновлять код, пока приложение работает и перезагружается по требованию. Возможно, эта перезагрузка происходит каждый раз, когда файл, содержащий код, изменяется или каким-то другим действием. Изменения в коде затем отражаются в приложении по мере его запуска. Нет необходимости закрывать программу и перекомпилировать ее и перезапустить.
В этом случае приложение представляет собой оконное приложение, которое имеет цикл обновления/рисования, скорее всего, использует OpenGL для графики, аудио-библиотеку для обработки звука (SuperCollider?) и в идеале сетевую библиотеку.
Конечно, я предпочитаю языки, хотя я не уверен, что любой из них был бы хорошо подходит для такого рода архитектуры. В идеале я бы использовал Python, Lua, Ruby или другой язык более высокого уровня. Однако друг недавно предложил Clojure как возможность, поэтому я тоже рассматриваю это.
Я хотел бы знать не только то, что языки будут подходящими для такого рода фреймворков, но, как правило, какие языковые функции создадут такую структуру, как эта возможность.
Ответы
Ответ 1
Clojure имеет почти все, что вы, скорее всего, захотите, как живой язык кодирования. Основные моменты:
- Интерактивный REPL - чтобы вы могли напрямую взаимодействовать с вашей программой. Даже когда я занимаюсь "традиционным программированием", я стараюсь писать код в интерактивном режиме и копировать бит, который мне нравится, в исходный файл позже. Clojure предназначен только для работы таким образом - почти все в вашей программе проверяется, модифицируется и заменяется во время выполнения.
- Великая поддержка concurrency - вы можете запускать параллельные фоновые задачи тривиально с кодом типа
(future (some-function))
. Что еще более важно, Clojure STM и акцент на высокопроизводительных неизменяемых структурах данных позаботятся о более тонких аспектах concurrency (например, что произойдет, если я обновляю текущую структуру данных, пока она находится в середине визуализации?)
- Доступность библиотеки - это язык JVM, поэтому вы можете использовать все аудиовизуальные, визуальные, IO или вычислительные средства, требуемые от экосистемы Java. Легко обернуть их в строку или две из Clojure, чтобы вы получили краткий интерфейс к тем функциям, которые вам нужны.
- Макросы - как Clojure является гомоиконным языком, вы можете воспользоваться способностью Lisp писать мощные макросы, расширяющие язык. Вы можете эффективно построить точный синтаксис, который вы хотите использовать в живой среде, и дать компилятору всю тяжелую работу по созданию полного кода за кулисами.
- Динамическая типизация - преимущества этого могут быть аргументированы в обоих направлениях, но это, безусловно, огромная выгода при попытке писать код быстро и лаконично.
- Активное сообщество с множеством интересных проектов. В сообществе Clojure вы, вероятно, найдете много людей, заинтересованных в подобных методах живого кодирования.
Несколько ссылок, которые могут вам понравиться:
Ответ 2
Я реализовал функцию живого кодирования в Lua как часть ZeroBrane Studio IDE. Он работает точно так же, как вы описали при перезагрузке приложения при изменении кода. Я работаю над возможными улучшениями для изменения значений во время выполнения, чтобы избежать полной перезагрузки приложения. Это чистое решение на основе Lua и не требует каких-либо изменений в VM.
Вы можете увидеть демо-версию живого кодирования, как в настоящее время реализовано здесь: http://notebook.kulchenko.com/zerobrane/live-coding-in-lua-bret-victor-style.
В отношении используемых/обязательных языковых функций я полагаюсь на:
- возможность прерывания/возобновления запущенного приложения (это основано на вызовах debug.hook и error()),
- возможность удаленного взаимодействия с (немодифицированным) приложением (это делается на основе debug.hook, взаимодействия TCP с поддержкой select() для обнаружения, если новый запрос также отправляется с главной машины, а также на сопрограммы для переключения между основным приложением и модулем живого кодирования) и
- возможность ввода нового кода в приложение (этот механизм также использует совлокальные подпрограммы, но я уверен, что есть альтернативы). Существует также возможность вводить только модифицированный фрагмент, но он должен быть на уровне функции, и если эта функция является локальной для какой-либо другой функции, вам необходимо включить ее и т.д.
Ответ 3
Единственное, что необходимо сделать для этой работы, это форма динамической привязки, например, передача сообщений в Erlang или eval
на многих других языках.
Если у вас есть динамическое связывание, вы можете изменить цель сообщения, не затрагивая сообщение, или сообщение, не затрагивающее цель, при условии, что цель определена при попытке отправить сообщение на нее, а также сообщение определяется для целей, к которым вы его отправляете, когда вы отправляете их.
При изменении цели все, что вам нужно сделать, - это отправлять сообщения в предыдущую версию до тех пор, пока не будет установлена новая версия, а затем сделайте небольшое заблокированное обновление для перехода к новой версии. Аналогично, при изменении сообщения вы просто ставите старую версию до тех пор, пока не появится новая.
Однако код с возможностью горячей замены должен быть сконструирован как таковой, однако приложение должно быть достаточно модульным, чтобы замена реализации компонента не вызывала прерывания, и это может произойти только при тщательном программировании.
Ответ 4
Хорошо и хорошо иметь "живое кодирование" в вашем блоке dev, но способ прямого взаимодействия с развернутым сервером делает его намного ближе к тому, чтобы быть "реальным". Для этого вам понадобится сетевой REPL.
clojure обеспечивает это красиво в виде socket repl. Это позволяет удаленно подключаться к текущей версии вашего кода на вашем развернутом сервере tomcat (например). Затем вы можете прикрепить свой любимый инструмент разработки с поддержкой swank и взломать.
Ответ 5
Tcl уже есть. Например, вы можете написать программу gui, которая создает отдельное окно с интерактивным приглашением. Оттуда вы можете перезагрузить свой код, ввести новый код и т.д.
Вы можете сделать это с помощью любого инструментария gui, хотя некоторые из них будут намного сложнее других. Это должно быть легко с python, хотя отступы - IMHO - делает интерактивное использование сложным. Я уверен, что большинство других динамических языков могут сделать это без особых проблем.
Посмотрите на это так: если ваш инструментарий позволяет открывать несколько окон, нет причин, по которым одно из этих окон не может быть интерактивным приглашением. Все, что вам нужно - это возможность открыть окно и какую-то команду "eval", которая запускает код, переданный ему в виде строки.
Ответ 6
python на google appengine имеет repote_api_shell.py. это не полный комплект для живого кодирования - clojure на emacs w/swank- clojure имеет гораздо более реальное применение, поскольку интегрирует "livecoding" в ритмы повседневного развития, но многие люди не что это возможно в определенных средах python.
$ PYTHONPATH=. remote_api_shell.py -s dustin-getz.appspot.com
App Engine remote_api shell
Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]
The db, users, urlfetch, and memcache modules are imported.
dustin-getz> import models
dustin-getz> models.BlogPost(title='a modern take on automated testing', link='https://docs.google.com/document/pub?id=1DUxQogBg45rOTK4c5_SfEHiQcvL5c207Ivcy-gDNx2s', dont_publish_feed=False).put()
dustin-getz> items = models.BlogPost.all().filter('dont_publish_feed =', False).order('-published_date').fetch(100)
dustin-getz> len(items)
58
dustin-getz> for item in items[:5]: print item.title
a modern take on automated testing
Notes: Running a startup on haskell
the [un]necessity of superstar middle management in bigcos
"everything priced above its proper value"
stages of growth as a software engineer
Ответ 7
Я работаю над функцией живого кодирования для редактора PyDev Python. Это было вдохновлено Брет Виктором "Изобретение на принципе" , и я реализовал дисплей состояния программы, а также графику черепах. Они оба обновляются при вводе кода Python в Eclipse.
Проект размещен на GitHub, и я опубликовал демонстрационное видео, а также учебник.
Основными особенностями Python, которые я использовал, были абстрактные деревья синтаксиса и выполнение динамического кода. Я беру код пользователя, анализирую его на дерево, затем обрабатываю любые инструкции присваивания, итерации циклов и вызовы функций. Как только я обработаю дерево, я его выполнил и отобразил отчет или нарисовал требуемую графику черепахи.
Я не реализовал функцию обмена, которую обсуждают другие ответы. Вместо этого я всегда запускаю код до завершения или тайм-аута. Я предполагаю, что живое кодирование является улучшением разработки, основанной на тестах, а не как способ взломать живое приложение. Тем не менее, я буду больше думать о том, что позволит мне сделать замену части живого приложения.
Ответ 8
Smalltalk, вероятно, лучший вариант для этого. В отличие от других, у него есть целая среда IDE для живого кодирования, а не только REPL