Блочное программирование

image
Здравствуйте! Начну статью с небольшого отступления. Не посетило ли вас разочарование когда вы впервые столкнулись с программированием? Я предполагал что создание программ происходит путём взаимодействия с каким-то сложным, но очень интересным инструментом, в котором я смогу заниматься своим любимым делом (собирать конструкторы) на новом уровне. Однако, вместо этого мне пришлось изучать как писать текстовые файлы состоящие из различных операторов, скобок, строк и прочих текстовых конструкций. Прошли десятилетия, я научился программировать, и уж было позабыл про это разочарование, однако увидев в сети новость про Google Blockly и Scratch я почувствовал ностальгию…

Эти инструменты, даже не претендуя на профессионализм, так интересны! Никаких текстов и компиляций — таскаешь блоки и мгновенно получаешь результат. Можно ли сделать так для профессионалов? Уверен, что можно! И в этой статье я хотел бы выразить своё видение того как.

В чём суть?


Если мы уходим от тестового способа написания программ, нам необходимо разделить структуру кода программы и его вид…

Как это?


Для этого в первую очередь нам потребуется хранить исходные коды в другой форме. Они должны представлять собой описание инструкций и данных программы в одной из существующих форм хранения данных, таких как json, xml или любой другой. Этот файл (рисунок 1, слева) может иметь довольно безобразный вид и не поддаваться хоть сколько-нибудь разумному способу его прямого редактирования, однако в среде программирования он будет превращаться в блочный код (рисунок 1, справа).

image

Сама же среда программирования имеет дело не с текстовыми кодами, а с «блоками», из которых строится код программы.

Что нам это даст?


1. Во-первых, мы избавимся от несущественных отличий в синтаксисе различных языков. Например, блоки кода в С++ разделяются фигурными скобками, а Ruby обращает внимание на ключевые слова… В редакторе можно настроить и тот и другой вид программы, от этого не поменяется ничего в ней самой. Персональные настройки отображения позволят разработчику смотреть на программу так, как ему нравится. Кроме того, мы сможем использовать любые символы при именовании, включая пробелы.

image

2. Во-вторых, увеличится скорость написания программы. Сейчас для того, чтобы написать оператор for в С-подобном языке нам нужно написать сам текст for, затем скобки, параметры, точки с запятыми, фигурные скобки, и нажать клавишу ввод. В нашем же варианте среда программирования по нажатию на определенное сочетание клавиш вставит цикл и потребует только ввести его параметры. Например, по нажатию на «f» поставит на место курсора цикл for и предложит ввести количество повторений и название счётчика через табуляцию, нажав клавишу ввод в конце.

image

3. В-третьих, можно будет обеспечить независимость от языка программиста. Операторы языка могут обозначаться некоторыми символами или же ключевые слова могут отображаться на родном языке программиста. Если он хочет чтобы операторы назывались по-английски, по-русски или на любом другом языке, он выбирает этот язык в настройках редактора и названия операторов меняются «на лету». Насчёт имён объектов и методов посложнее, но в любом случае, если программа разрабатывается русскими разработчиками, то и именовать всё можно по-русски — в случае выбора этого сценария не будет никакого несоответствия между названиями операторов и названиями объектов и методов — всё будет на русском. Это может упростить обучение для школьников и взрослых, незнакомых с английским языком. Да и к тому же в многонациональных командах есть возможность использовать для именования объектов и методов два названия — на английском и на языке разработчика.

image

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

image

image

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

Среда программирования


Такой способ представления программы уже не позволит менять её в простом текстовом редакторе. Для редактирования программы понадобится особая среда программирования. Разработать первую версию этой среды программирования сложнее чем для традиционных языков, но есть способы начать попроще. Например, можно начать с редактора файлов данных, позволяющего редактировать файлы любых форматов (xml, json, yaml и т. д.) одним и тем же способом — с помощью блоков. В этом случае пользователь будет избавлен от необходимости изучать синтаксис этих файлов и сможет редактировать любой из них научившись редактировать файлы данных лишь в этой программе.

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

Заключение


Я уверен, что описанный способ программирования откроет огромные возможности для программистов и в значительной степени ускорит и упростит разработку приложений. Однако один в поле не воин. Разработка подобного продукта требует могучего подхода и ресурсов. Я одиночка и работаю удалённо — мне этот проект не по зубам… Возможно, если вы заинтересовались им, мы могли бы поработать вместе?
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 41

    +17
    >откроет огромные возможности для программистов
    Не откроет. Думаете, вы первый? Таких идей уже было миллион. В лучшем случае из них как-то работает и не умерло — от силы процентов 5. Почему? Да потому что у этой идеи есть куча очевидных и менее очевидных недостатков. Например, самый очевидный — раз код не текст, значит вам не годятся все те инструменты, которые были сделаны человечеством для текстов, включая программистские типа diff, например. Значит вам придется сделать свое версионирование, допустим.

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

    А самое главное — вы пытаетесь решать несуществующие проблемы. Или несущественные. Отличия в синтаксисе языка? Это такая неважная хрень. Я обычно пишу в одном проекте примерно на 4-5 языках, и у них у всех разный синтаксис в вашем смысле. Не напрягает ну совсем, для этого как раз давно есть текстовые редакторы и IDE.

    Скорость разработки, путем подстановки цикла одной кнопкой? Ой, откройте для себя скажем IDEA, там это есть года так с 2005, не позже. Для Java, и других языков тоже. И да, сюрприз — если бы в жизни скорость разработки ограничивалась только этим…
      –1
      Да, пожалуй я слишком мало внимания уделил основному. Самая существенная решаемая проблема — это длительная компиляция программ на текстовых языках. При блочном программировании есть возможность в реальном времени «достраивать» программу в оперативной памяти. В этом случае было бы два режима выполнения разрабатываемой программы — в режиме «редактирования» и в «финальном» режиме. В первом случае программа запускается параллельно со средой разработки и среди кодов программы содержатся вспомогательные данные, позволяющие менять и соединять изменённые объекты программы на лету, однако сама программа из-за этого выполняется медленнее. Во втором режиме всё лишнее отбрасывается и программа компилируется для выполнения с максимальной производительностью. Второй режим — это, по сути, традиционная компиляция.

      Во вторых есть ещё одна хорошая возможность в том случае если программа выполняется в первом режиме. Можно построить речевой анализатор, который будет распознавать речевые команды, отдаваемые человеком и на их основе изменять устроение программы. Можно было бы отдавать команды вроде «Создай новое окно», «Когда нажимают на эту кнопку отправляй почту по адресу» или чего посложнее (в зависимости от развитости этого анализатора). И эта суб-программа вносила бы изменения в разрабатываемую программу. Во многих случаях речевое взаимодействие было бы очень полезно. Сказать что-то в микрофон зачастую гораздо быстрее чем использовать мышь с клавиатурой, к тому же это избавило бы от чтения многих страниц документации.
        +1
        Самая существенная решаемая проблема — это длительная компиляция программ на текстовых языках.

        … ну вот на C#, например. Длительная?


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

        А что мешает сделать это с "традиционным" языком программирования?

          0

          Подскажите, сколько времени происходит компиляция программы на питоне? Или на js?
          А как насчет instant run в Android с компилируемой джавой?

        0

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

          +2
          Похоже на Java и .Net, не правда ли?
            0

            Очень отдаленно. В комментариях ниже есть ссылка интересная на эту тему.

            0
            Да, но я возможно зря акцентировал внимание именно на этом. См. комментарий выше.
            +5
            описанный способ программирования откроет огромные возможности

            Действительно, как говорит sshikov, таких «конструкторов» существует очень много.
            Если бы вы начинали с этих конструкторов, то осознали бы, что идея написания кода — это эволюция, логическое продолжение идеи компоновки блоков.

            Когда вы попробуете написать действительно полезную, важную, большую программу на блоках, все описанные «плюсы» начнут вам только мешать.
            1. Синтаксиса не будет, но возникнет проблема выбора блоков из аналогов, их совместимости и прочего, что вы можете наблюдать в npm.
            2. В реальности, написать пару скобок, даже не смотря на клавиатуру, гораздо быстрее, чем найти нужный блок в каталоге, перетащить его мышкой и соединить с другими блоками. Учтите, что таких блоков очень много.
            3. Ну это вообще бред. Если только вы не продаете вместо готовых программ их исходники в магазине, то язык программирования влияет. Кроме того, имеет смысл передавать не код, а алгоритм.
            4. Тут вы совсем забыли про компиляторы, библиотеки, автоматическое форматирование и оптимизацию.
            5. Представление никак не зависит от кода/блоков. Составьте дерево синтаксическое/вызовов/иерархий и рисуйте его в виде комнаты. Но, важно заметить, что самый эффективный способ программирования — однонаправленный однопоточный непрерывный ввод символов с клавиатуры. Просто потому, что создаётся рефлекс, и вам уже не требуется обращать внимание на клавиатуру или набранный код.
              +1
              Именно. Что есть блок? Какие у него свойства, и как их можно компоновать друг с другом? Как гарантируется, что композиция будет правильно работать? Вот это все существенные вопросы, а синтаксис — это такая десятая по счету фигня, не то чтобы не важная, но явно не решающая.
              +2

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

                –7
                Ух… Давайте сразу ответим на главный вопрос вы тролль? Нет?! Тогда каков ваш опыт разработки, на каких языках и какие парадигмы программирования вы использовали?
                Потому что современные языки программирования именно и работают с блоками. Пакеты, библиотеки, фреймворки, ООП это всё именно и есть тот набор блоков из которых мы и собираем программы. При этом можно в любой момент взять и немного изменить блок под себя не переступая через барьер.
                  +6
                  Во-первых, мы избавимся от несущественных отличий в синтаксисе различных языков.

                  Языки отличаются не только синтаксисом, но и семантикой. for в С++ — не то же самое, что for в паскале, scala или питоне. Если избавиться от отличий, получится весьма невыразительный язык.


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

                  Для программирования нет ничего быстрее при записи и нагляднее при чтении, чем текст. Графические инструменты (например, scratch, и даже мёртвый ДРАКОН ) уже существуют, но медленны и годятся только для простых программ.


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


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

                  Будет ли это удобнее? Может быть, вместо UML диаграмм пакетов/классов/объектов трёхмерная комната будет выглядеть нагляднее. Но, имхо, не вместо for'ов и while'ов внутри функции.


                  P.S. И как вы представите в одинаковых графических блоках C++ и Хаскель?

                    –1
                    | Графические инструменты (например, scratch, и даже мёртвый ДРАКОН )
                    | уже существуют, но медленны и годятся только для простых программ.

                    Не совсем мёртвый, и есть определённая изюминка его использования в общем процессе разработки программ. :)

                    Пример темы на форуме Дракон языка Преимущества языка ДРАКОН для деревьев принятия решений (код может генерироваться на разные языки программирования)

                    +1

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


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

                      0
                      Если я верно понимаю, похожий подход декларировал еще Visual Basic почти тридцать лет назад. И казалось, что вот еще немножко, и тот унылый текст, который приходится писать для того, чтобы сделать вот эти волшебные кнопочки, перетаскиваемые мышкой на формочку, функциональными — еще немножко, и этот текст тоже превратится в блоки, таскаемые мышкой…

                      И еще: только не примите, пожалуйста, в свой адрес, поскольку вольная ассоциация.
                      В самом начале нулевых одна моя знакомая очень, очень ждала двух вещей. Хороших автопереводчиков, ибо не хотела учить английский, и хорошую распознавалку речи, ибо не хотела учиться печатать. Ей же было уже тридцать пять, жизнь практически позади и все эти технические подробности на самом деле нужны только затем, чтобы подвести некоторые итоги в этой самой уже прошедшей жизни.
                      Ждет до сих пор.
                        0
                        Извините, так кнопочки ведь работали.
                          +2
                          Возможно, я вас не очень понял.
                          Кнопочки работали, но чтобы они что-то делали, это что-то нужно было прописать унылым текстом. Сама по себе кнопочка могла нажиматься, отжиматься и отлавливать это состояние. А привязать к нажатию какой-нибудь там выход из программы надо было уже вручную.
                          Или я что путаю?
                            0
                            Пожалуй проект HiAsm (конструктор программ)
                            оправдавшийся проект для визуального программирования.
                              0
                              Какая прикольная штука… Спасибо.
                              0
                              Э-э-э вообще то еще в 90-е был Clarion, в котором программа автогенерилась, по структуре данных. Только в специальном «помощнике» нужно было указать вид приложения и какая таблица в какой форме как должна отображаться и редактироваться.
                              Так что не в кнопочках дело. :-)
                                +1

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

                                  0
                                  Там в основном был генерация CRUD приложений, к которым потом нужно было нагенерить отчетов.
                                  Особо сложной бизнес-логики не предполагалось.
                                  0
                                  Не знал про такое. Впрочем, я не то, что ненастоящий, я вообще не разработчик.
                                  Если я вас верно понял, то собственно там, где требовалась логика посложнее и гибкости побольше, он также оказывался неприменим?
                                    0
                                    Ну почему?
                                    Просто если нужно было совсем не стандартное, то надо было писать код, как обычно.
                                    Например мой коллега писал программу, для приема документов в ВУЗ.
                                    Быстро накидал прототип с отчетами. А потом ручками дописывал кучу ФЛК, чтобы операторы не могли ввести фигню.
                                      0
                                      если нужно было совсем не стандартное, то надо было писать код, как обычно.
                                      Да, я это и имел в виду.
                                      Самые базовые вещи автоматизируются, и могут быть представлены графически. Но шаг влево, шаг вправо, и от написания кода руками деться некуда. Собственно, это была моя основная мысль с первого коммента начиная, но похоже, я в этом треде несколько косноязычен.
                                        0
                                        Да конечно. Clarion в основном подходил для CRUD приложений.
                                        Просто, например, когда я попробовал Delphi, который расхваливали, что программы там рисуются.
                                        У меня было эмоции «ЧТА? Эта штука не умеет, того что давно умеет Clarion под DOS»

                            +1
                            Для этого в первую очередь нам потребуется хранить исходные коды в другой форме.

                            … ну то есть хранить сериализованное синтаксическое дерево.


                            Например, блоки кода в С++ разделяются фигурными скобками, а Ruby обращает внимание на ключевые слова… В редакторе можно настроить и тот и другой вид программы, от этого не поменяется ничего в ней самой. Персональные настройки отображения позволят разработчику смотреть на программу так, как ему нравится. Кроме того, мы сможем использовать любые символы при именовании, включая пробелы.

                            Как вы думаете, почему этого до сих пор не сделано? Помимо многих других ответов, есть один очень простой: производительность. Как вы ни старайтесь, обычный текстовый редактор вы не обгоните.


                            Сейчас для того, чтобы написать оператор for в С-подобном языке нам нужно написать сам текст for, затем скобки, параметры, точки с запятыми, фигурные скобки, и нажать клавишу ввод. В нашем же варианте среда программирования по нажатию на определенное сочетание клавиш вставит цикл и потребует только ввести его параметры. Например, по нажатию на «f» поставит на место курсора цикл for и предложит ввести количество повторений и название счётчика через табуляцию, нажав клавишу ввод в конце

                            Вы про сниппеты никогда не слышали?


                            В-третьих, можно будет обеспечить независимость от языка программиста.[...] Насчёт имён объектов и методов посложнее, но в любом случае, если программа разрабатывается русскими разработчиками

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


                            В-четвертых появится возможность обновления структуры программы.

                            Она и сейчас есть. Возьми исходники, разбери в дерево, обнови, сохрани обратно.


                            В-пятых представлять структуру программы можно будет любым удобным для того способом.

                            Она и сейчас есть. Возьми исходники, разбери в дерево, визуализируй как хочется.


                            В каком-то смысле, ваш подход (редактируй не то, что хранится в файле) напоминает миллион существующих визуальных редакторов (форм, веб-страниц, рабочих процессов, схем БД). И все равно люди, которым нужен контроль за происходящим, спускаются на уровень исходников, потому что визуальный редактор нужного контроля не дает. Так будет и у вас — в итоге вы сделаете еще один язык программирования, такой же, как другие, просто с визуальным редактором.

                              0

                              Blockly и Scratch хороши для детей/начинающих, т.к. внешняя простота достигается за счёт того, что ограничения универсальности спрятаны "под капотом". Импорт нужных модулей, например.
                              Делали программатор полётов для Bitcraze на Blockly.
                              Вот как выглядел оригинал на Питоне:


                              import logging
                              import sys
                              import time
                              
                              import cflib.crtp
                              from cflib.crazyflie import Crazyflie
                              from cflib.crazyflie.syncCrazyflie import SyncCrazyflie
                              from cflib.positioning.motion_commander import MotionCommander
                              from cflib.utils.multiranger import Multiranger
                              
                              URI = 'radio://0/80/2M'
                              
                              if len(sys.argv) > 1:
                                  URI = sys.argv[1]
                              
                              # Only output errors from the logging framework
                              logging.basicConfig(level=logging.ERROR)
                              
                              def is_close(range):
                                  MIN_DISTANCE = 0.2  # m
                              
                                  if range is None:
                                      return False
                                  else:
                                      return range < MIN_DISTANCE
                              
                              if __name__ == '__main__':
                                  # Initialize the low-level drivers (don't list the debug drivers)
                                  cflib.crtp.init_drivers(enable_debug_driver=False)
                              
                                  cf = Crazyflie(rw_cache='./cache')
                                  with SyncCrazyflie(URI, cf=cf) as scf:
                                      with MotionCommander(scf) as motion_commander:
                                          with Multiranger(scf) as multi_ranger:
                                              keep_flying = True
                              
                                              while keep_flying:
                                                  VELOCITY = 0.5
                                                  velocity_x = 0.0
                                                  velocity_y = 0.0
                              
                                                  if is_close(multi_ranger.front):
                                                      velocity_x -= VELOCITY
                                                  if is_close(multi_ranger.back):
                                                      velocity_x += VELOCITY
                              
                                                  if is_close(multi_ranger.left):
                                                      velocity_y -= VELOCITY
                                                  if is_close(multi_ranger.right):
                                                      velocity_y += VELOCITY
                              
                                                  if is_close(multi_ranger.up):
                                                      keep_flying = False
                              
                                                  motion_commander.start_linear_motion(
                                                      velocity_x, velocity_y, 0)
                              
                                                  time.sleep(0.1)
                              
                                          print('Demo terminated!')

                              Вот как выглядит у нас на Блокли:


                              Летает одинаково, вот так:



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

                                0
                                устранить артефакты на этапе конвертации из Блокли в исполняемый код

                                Таких просто не должно быть. А с остальным согласен.

                                +1
                                Судя по рендерингу шрифтов и цветовой схеме автор использует Brackets. Просто переходите на любой другой редактор и отношение к текстовым языкам изменится!
                                Ну а вообще по теме визуала более интересным выглядит что-то в стиле JetBrains MPS
                                www.youtube.com/watch?v=XolJx4GfMmg
                                  0
                                  Шо, опять? Сколько уже её было, этой визуальщины, но ЧСХ, подавляющая часть ПО как писалась, так и пишется на нормальных языках.
                                    +2

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


                                    def filter_strings(data):
                                       return [
                                         x for x in data if isinstance(x, str)
                                       ]
                                    
                                    data = '[1, 2, "hello"]'
                                    smth = filter_strings(json.loads(data))
                                      0
                                      Надо было сразу так что бы ТС не жалеть:
                                      smth = list(filter(lambda x: isinstance(x, str), json.loads('[1, 2, "hello"]')))

                                      А если по сути, то в вашем примере нет ничего такого кроме вызова готового модуля, встроенной функции и генератора списков.
                                        +1

                                        Ну я все таки старался написать читаемый код.
                                        И в нем есть ещё одна важная вещь: проверка типа переменной в рантайме

                                        0

                                        Ваш код довольно-таки тривиально транслируется в цикл с if'ом. А могло быть и хуже:


                                        немного комбинаторных парсеров
                                        object FormulaParser extends RegexParsers with PackratParsers {
                                        
                                            def id: Parser[Id] = "[a-zA-Z][a-zA-Z0-9_]*".r ^^ Id
                                        
                                            def number: Parser[Number] = "-" ~> number ^^ (n => Number(-n.value)) |
                                                ("[0-9]+\\.[0-9]*".r | "[0-9]+".r) ^^ (s => Number(s.toDouble))
                                        
                                            def funcCall: Parser[FuncCall] = id ~ ("(" ~> expression <~ ")") ^^ {case id ~ exp => FuncCall(id, exp)}
                                        
                                            def value: Parser[Expression] = number | funcCall | id | ("(" ~> expression <~ ")")
                                        
                                            lazy val term: PackratParser[Expression] = term ~ ("*" | "/") ~ value ^^ binOperation | value
                                        
                                            lazy val expression: PackratParser[Expression] = expression ~ ("+" | "-") ~ term ^^ binOperation | term
                                        
                                            private def binOperation(p: Expression ~ String ~ Expression) = p match {
                                                case e1 ~ op ~ e2 => BinOperation(e1, BinOperator(op), e2)
                                            }
                                        
                                            def apply(code: String): Either[ParserError, Expression] =
                                                parse(expression, new PackratReader(new CharSequenceReader(code))) match {
                                                    case Success(result, next) => Right(result)
                                                    case NoSuccess(msg, next) => Left(ParserError(msg))
                                                }
                                        
                                            case class ParserError(msg: String)
                                        }
                                        
                                        sealed trait Expression
                                        
                                        case class BinOperator(operator: String)
                                        
                                        case class Number(value: Double) extends Expression
                                        case class Id(name: String) extends Expression
                                        case class BinOperation(left: Expression, op: BinOperator, right: Expression) extends Expression
                                        case class FuncCall(funcName: Id, argument: Expression) extends Expression
                                        
                                        object Evaluator {
                                            def apply(expression: Expression,
                                                      variables: (String) => Double = Map.empty,
                                                      functions: (String) => (Double) => Double = Map.empty): Double = {
                                        
                                                def eval(exp: Expression) = this (exp, variables, functions)
                                        
                                                expression match {
                                                    case Number(value) => value
                                                    case Id(name) => variables(name)
                                                    case BinOperation(left, op, right) => operator2func(op)(eval(left), eval(right))
                                                    case FuncCall(funcId, expr) => functions(funcId.name)(eval(expr))
                                                }
                                            }
                                        
                                            def operator2func(binOperator: BinOperator): (Double, Double) => Double =
                                                binOperator.operator match {
                                                    case "+" => (a, b) => a + b
                                                    case "-" => (a, b) => a - b
                                                    case "*" => (a, b) => a * b
                                                    case "/" => (a, b) => a / b
                                                }
                                        }
                                        
                                        object Main extends App {
                                            def eval(code: String,
                                                     variables: (String) => Double = Map.empty,
                                                     functions: (String) => (Double) => Double = Map.empty) = {
                                                val parsed = FormulaParser(code)
                                                parsed.left.foreach(error => println(s"\'$code\' parsing error: $error"))
                                                parsed.right.map(expr => Evaluator(expr, variables, functions)).foreach(d => println(s"\'$code\' = $d"))
                                            }
                                        
                                            eval("1")
                                            eval("0.1")
                                            eval("1.")
                                            eval("  1  ")
                                            eval("-0.1")
                                        
                                            eval("1+2")
                                            eval("2-1")
                                            eval("2*3")
                                            eval("4/2")
                                        
                                            val vars = Map(
                                                "pi" -> math.Pi,
                                                "e" -> math.E)
                                        
                                            val funcs: (String) => (Double) => Double = Map(
                                                "sin" -> math.sin,
                                                "cos" -> math.cos,
                                                "inc" -> { d: Double => d + 1 }
                                            )
                                        
                                            eval("pi", vars)
                                            eval("inc(e)", vars, funcs)
                                        
                                            eval("2+2*2")
                                            eval("1+2*(3+4*5)")
                                            eval("8/2/2")
                                            eval("8-1-2")
                                        
                                            eval("1. + 2.0 * sin(pi / 2)", vars, funcs)
                                        }

                                        (взято отсюда)


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


                                        Но с другой стороны, блоки — тоже DSL, только графический, а не текстовый.

                                          0
                                          Ваш код довольно-таки тривиально транслируется в цикл с if'ом.

                                          Это пока в целевом языке есть возможность определить тип объекта во время выполнения.


                                          (я тоже с первого раза не заметил, в чем дело)

                                            0
                                            Собственно нет ни какой проблемы реализовать это же в «блоках» если будет такой функционал.
                                            Проблема в том что ТС во первых решает проблему которой нет, второе ТС не особо понимает почему же кроме различий в синтаксисе есть разные языки и почему тот или иной используется в той или иной сфере.
                                              +2
                                              Собственно нет ни какой проблемы реализовать это же в «блоках» если будет такой функционал.

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


                                              Объем работы — это тоже проблема.

                                                +1
                                                Лично меня больше волнует две вещи. Первое, графическая компоновка блоков чрезмерное усложнение — это не быстрее и не проще чем писать код в хорошей IDE. Второе слишком высокий уровень абстракции, когда от компоновки готовых блоков будет очень тяжело перейти к написанию собственных(у меня есть собственный печальный опыт).
                                                А свою стандартную библиотеку для всех языков не обязательно писать, скорей всего придётся делать свой интерпретатор с преферансом и девушками лёгкого поведения, а если опираться на существующие языки, то можно выбирать язык в зависимости от необходимых фич, и просто обеспечить согласованность работы и передачи данных между блоками. Как ТС это собирается это сделать у него уже спрашивали.
                                                  0
                                                  Скорее всего писать «обертку» для каждого языка придется, ибо не все языки имеют одинаковые возможности и средства написания. Т.е. сперва привести к общему знаменателю.
                                                  Конечно можно написать и интерпретатор для каждого языка, но сути это не меняет. Производительности таким образом теоретически можно добитться большей, но сложность реализации на порядок возрастет, на мой взгляд.

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

                                      Самое читаемое