Anatoly Levenchuk (ailev) wrote,
Anatoly Levenchuk
ailev

Две большие фичи Julia и инженерное шапкозакидательство на их основе

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

Для меня в Julia две больших фичи:

1. Похоже, что Julia решает "автомагически" большое количество проблем, связанных с модульностью. Менеджер пакетов, который интегрирован в Julia и умеет брать нужные пакеты из GitHub тут не самое главное. То, что библиотеки на Си в Julia "как родные", а её собственные библиотеки пишутся на Julia -- это тоже не главное.

Главное -- это именно multiple dispatch в сочетании с опциональной типизацией и выводом типов. Это позволяет решить expression problem (https://en.wikipedia.org/wiki/Expression_problem -- The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts)) -- отдельно пополнять алгоритмы и структуры данных, причём не теряя в производительности и не залезая внутрь уже имеющегося кода. Это ключ к модульности, платформенности, созданию библиотек. Явление примерно того же порядка, что акаузальность в Modelica (http://modelica.org), только в обычном языке программирования. Пополнить код новыми типами данных и процедурами можно без перекомпиляции уже имеющихся библиотек и потери в производительности, в этом фишка. И не путайте multiple dispatch с перегруженными операторами, это не про синтаксис вообще!

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

Stephan Karpinski заметил 20 декабря 2014 -- "How hard it is to explain how effective multiple dispatch is, is itself quite interesting", https://github.com/JuliaLang/julia/issues/8839. Это примерно так же трудно, как объяснять, почему акаузальная Modelica лучше всяких других традиционных языков типа SimuLink или даже Matlab. Любые средства повышения модульности (часто в языках она путается ещё и с гранулярностью) трудно объяснить. Если не понимаешь про важность модульности, про programming-in-the-large (http://www.cs.umd.edu/class/spring2005/cmsc838p/General/pitl.pdf, https://en.wikipedia.org/wiki/Programming_in_the_large_and_programming_in_the_small), то никакие объяснения не пойдут тебе впрок.

Я писал подробней про multiple dispatch и его важность в Julia в "Exploratory programming, Julia и графовые базы данных -- что в них общего?" (http://ailev.livejournal.com/1140646.html, и там ссылки на комментарии Graydon Hoare ключевые). Демонстрация multiple dispatch в ноутбуке от лидера команды Julia: http://nbviewer.ipython.org/gist/StefanKarpinski/b8fe9dbb36c1427b9f22 (там ударная концовка про протоколы, которым нужно абстрагирование: функция plot во всех графических пакетах должна бы быть одной и той же!).

Механизмы работы с типами в Julia нельзя недооценивать. Вот, например, рантаймовая специализация типов: http://sober-space.livejournal.com/109234.html

Мы беседовали о важности обеспечения модульности (повторной используемости в том числе) и решения expression problem с командой Hello World! Technologies, http://hwdtech.ru. Эта команда сделала свой вариант "базы процедур" на базе акторной нашлёпки на код традиционных систем программирования. Их система СУБП (систему управления базами процедур) симметрична СУБД для управления данными. Вызовы процедур превращались в обмен сообщениями, параметры при этом парсировались, и жизнь с распухающей базой кода немедленно после этого налаживалась как жизнь после использования СУБД при распухании данных. Фишка тамошнего подхода -- это использование принципов SOLID -- http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod. Более того, на базе алгебры Хоара эти принципы SOLID были математически обоснованы (http://hwdtech.ru/happydevlite-%D0%BE%D1%81%D0%B5%D0%BD%D1%8C-2015/, http://hwdtech.ru/dev2dev-may-2015/). Всё это про одно и то же: модульность, повторное использование, SOLID, алгебра Хоара, multiple dispatch и type inference. Темы это все разные, но это всё движение в одну сторону: модульность в данных, модульность в коде, повторноиспользуемость/платформизация.

2. В Julia есть мощные средства интроспекции (код программы -- данные для неё же) и метапрограммирования (язык можно всегда расширить, в нём есть встроенные средства генерации кода) -- их делали по образу и подобию Lisp. Да, Julia может считаться не только наследником Fortran, Mathlab и Python, но и Lisp -- для многих это неожиданность.

Julia тем самым является расширяемым языком программирования, на ней возможна реализация domain-specific programmin languages, DSL. Вот несколько моих старых (2008-2009г.г., с тех пор прошла целая вечность, поколения в софте меняются ведь каждые пять лет) постов про DSL и языкоориентированное программирование:
-- Языко-ориентированный подход. Серая бумага. http://ailev.livejournal.com/545386.html
-- языкоориентированное и предметноориентированное программирования. http://ailev.livejournal.com/548142.html
-- Йa -- язычнег, дайте мне капище: http://ailev.livejournal.com/683311.html
-- и потом было довольно много текстов про language workbench (где языки должны были задаваться декларативным методом в рамках какой-то специализированной IDE, где они могли бы смешиваться при написании программ).

В итоге всего этого движения выяснилось: языки с развитым метапрограммированием и интроспекцией вполне заменяют эти воркбенчи (точнее, их IDE и есть эти самые language workbenches -- http://www.languageworkbenches.net/). А DSL удобней всего встроенные (embedded), а не stand-alone. Тема языкоориентированного программирования как "каждую задачу нужно решать на её языке" осталась, тема инструментария свелась к языкам, которые хорошо для этого приспособлены.

При этом моя личная неудовлетворённость нынешним ООП была довольно большой (уж не знаю почему: исторически), и я всё пытался куда-то от ООП отвертеться: и семантикой-онтологиями увлекался (где внятно объяснялось, почему ООП -- зло, "что в одном проекте объект, в другом -- атрибут, и наоборот") и конкатенативными/стековыми языками (Factor, новейшая инкарнация Forth). Функциональное программирование хорошо, но мне всегда казалось, что инженеров натренировать быть хорошими функциональными программистами было бы чересчур -- ведь даже программисты в эту страну попадают с трудом, несмотря на желание: и нельзя сказать, слишком ли высока там планка, или просто планку поставили в неправильном месте, где прыгать только хочется, но по факту не нужно. Вот с онтологиями ровно та же история, что с функциональным программированием: тоже планка не слишком высока, и всем любопытно и хочется, но до массового движения дело не доходит.

Если считать, что язык программирования -- это выражение логики, то к языкам программирования полностью применим посыл van Bethem: "К примеру, говорить о логике как о науке,цель которой в значительной мере определяется поиском определенного баланса между выразительной силой формальных языков и многосложностью их использования при решении таких задач как осуществление контроля за согласованностью, адекватностью моделирования и правильностью вывода" (http://ailev.livejournal.com/915253.html). Чем выразительней язык, тем меньше людей на земном шаре способны им воспользоваться. Но сделайте язык, которым сможет воспользоваться любой дурак -- и только дураки и будут им пользоваться. Каждый раз, когда вы решаете проблему помощи человеческому интеллекту ("помогаете играть на скрипке"), вы убеждаетесь, что никто не хочет учиться играть на скрипке -- ваша помощь чем круче, тем нужна меньшему числу людей ("никто не хочет играть на XYZ" -- http://ailev.livejournal.com/1158826.html).

Язык программирования тем самым должен как-то учитывать архитектуру как wetware (чтобы на нём было возможно хоть какое-то массовое программирование), так и hardware (чтобы он имел возможность как-то быть исполняемым на массовом железе). Мало кто понимает архитектуру wetware, хотя призывов использовать в языкостроении знание нейропсихологии, психологии, социологии и т.д. -- этих призывов много, знатоков-то человеческих мозгов хватает. Не хватает экспериментов. Особенно если учесть, что после тренинга человеческие мозги адаптируются к новым операциям, и все эксперименты можно проводить заново. Весь вопрос тут оказывается в крутости кривой обучения и ограниченности бюджета времени на обучение.

Мне кажется, что Julia достаточно простой язык для освоения инженерами. Уж проще Haskell это точно, а с Python нужно сравнивать специально -- тут нужны эксперименты, на глазок и "экспертным мнением" тут ничего сказать нельзя. При этом в ней есть средства поднятия выразительности -- метапрограммирование, усложнять язык можно по потребности. Так, средства ленивых вычислений и парсеры грамматик, равно как и всякая хитрая символьная математика в язык вводятся именно через метапрограммирование: https://github.com/svaksha/Julia.jl/blob/master/Programming-Paradigms.md, https://github.com/svaksha/Julia.jl/blob/master/Mathematics.md, https://github.com/svaksha/Julia.jl/blob/master/AI.md. Показательны тут эксперименты в использовании Julia для создания algebraic proof-assistant: http://sober-space.livejournal.com/108989.html. Вот PEGParser в макросах -- https://github.com/abeschneider/PEGParser.jl

C другой стороны, классические мультипарадигмальные языки (в которых разных парадигм по паре "из коробки") почему-то не взлетают. Видно, человеческий ум не так уж мультипарадигмален "из коробки", как о нём думают. И поэтому язык должен вырастать с этим умом: освоил новую парадигму -- включи её в язык, но включи потом. А исходный язык должен быть минимально парадигмален, как машинный код. Ну хорошо, как следующий уровень абстракции над машинным кодом.


3. А теперь обещанное в заголовке инженерное шапкозакидательство на основе двух упомянутых фич Julia.

Изо всех языков программирования, моделирования, онтологизирования (я продолжаю утверждать, что это одно и то же) я бы на сегодня выделил три: ArchiMate, Modelica и Julia. Я много об этом писал уже, но сейчас попробую написать безумный план:
[футуристический бред on]
-- на Julia можно попробовать реализовать акаузальный язык мультифизического имитационного моделирования (по мотивам Modelica). Солверов там уже хватает (https://github.com/JuliaLang/ODE.jl), а "компилятор со сбором системы уравнений по текстам модулей" можно делать средствами метапрограммирования. Можно отдельно подумать, что там останется от моделеориентированности и как будет выглядеть мультифизика с multiple dispatch, как будут выглядеть принципиальные схемы.
-- для принципиальных схем нужно будет написать коллективный моделер, как же без этого.
-- а на коллективном моделере Modelica-in-Julia можно написать ArchiMate-библиотеку, как обычную библиотеку, принятую в Modelica.
-- а поскольку Modelica из языка мультифизического моделирования потихоньку превращается в архитектурный язык и язык требований (http://incose-ru.livejournal.com/53170.html), то можно говорить о таком расширении Julia как об очередной инкарнации SysMoLan -- http://ailev.livejournal.com/1127145.html.
[футуристический бред off]
Не факт, что нужно думать в этом направлении, этот проект заранее неподъёмный в силу неохватности своего scope. В случае Modelica это удалось, правда, реализовать -- и язык программирования, и моделер, и решатель, и расширения на требования и архитектуру с рисовалкой принципиальных схем. Так что это 0.0001% шанса реализации чисто гипотетического сценария: что удалось сделать с Modelica может вдруг удастся сделать и с Julia.
[ещё раз футуристический бред off]
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

  • 25 comments