Как на самом деле формируется / создается новый язык программирования? - PullRequest
13 голосов
/ 30 апреля 2010

Fortran-> Algol-> Cpl-> Bcpl-> C-> C ++ -> Java .....

Похоже, что каждый язык построен на языке предка. Мой вопрос: новые языки расширяют родительские или есть какая-то хитрость?

например. System.out.print () в Java; это на самом деле printf () в C и так далее (printf на самом деле .. в Cpl)?

Если так, разве это не делает каждый следующий язык медленнее и требует больше памяти? Что отличает новый язык от фреймворка?

Ответы [ 12 ]

17 голосов
/ 30 апреля 2010

Как на самом деле создается / создается новый язык программирования?

Это многоступенчатый процесс:

  1. Теоретики с заостренными головами и другие профессионалы постоянно предлагают новые языковые возможности. Вы можете прочитать о них в таких местах, как Материалы симпозиума ACM по принципам языков программирования (POPL) , который проводится ежегодно с 1973 года.

  2. Многие из этих предложений фактически реализованы на некотором языке исследований ; некоторые исследовательские языки, которые я лично нахожу многообещающими, включают Coq и Agda. Haskell - бывший язык исследований, который сделал его большим. Исследовательский язык, который получает 10 пользователей, часто считается успешным. Многие исследовательские языки никогда не зашли так далеко.

    От исследований к развертыванию я знаю две модели:

  3. Модель A: Приходит талантливый любитель и синтезирует целый ряд существующих функций, возможно, включая некоторые новые идеи, в новый язык. У любителя есть талант, харизма и, возможно, убийственное приложение. Так рождаются C, Perl, Python, Ruby и Tcl.

  4. Модель P: Талантливый профессионал жертвует карьерой, чтобы создать и издать новый язык. Профессионал обладает талантом, глубокими знаниями в этой области и, возможно, убийственным приложением. Так рождаются Хаскелл, Луа, М.Л., Паскаль, Скала и Схема.

    Вы предлагаете другую модель:

  5. Модель E: Талантливый человек, любитель или профессионал, расширяет или изменяет другой язык. Есть встроенная база пользователей, которая может быть заинтересована в расширении. Возможно, пользователи смогут исследовать новые идеи без больших затрат на переход. Так рождаются C # и C ++.

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

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

Расширяют ли новые языки родительские?

Это на самом деле очень редко. C ++ является наиболее популярным примером, и, возможно, Algol-W или PL / S подошли близко. Но гораздо чаще использовать родительский язык только для вдохновения, и некоторые языки (на ум приходит Python) признают нескольких «родителей» в качестве источников вдохновения.

Разве это не делает каждый следующий язык медленнее и требует больше памяти?

Не обязательно. C ++ работает медленнее и использует больше памяти не потому, что он произошел от C, а потому, что он был разработан с течением времени до такой степени, что только очень опытный пользователь может надежно писать код C ++, который работает так же быстро, как и C код. (Я хочу быть очень ясным: дело не в том, что C ++ не может быть быстрым; дело в том, что стоимость кода C всегда очевидна при чтении исходного кода, а стоимость кода C ++ иногда совсем не очевидна при чтении исходного кода. ) Для получения дополнительной информации об эволюции C ++ прочитайте книгу Джима Уолдо Эволюция C ++ .

Изначально Java работала медленно из-за своевременной компиляции и других дурацких вещей в реализации. Они также оседлали себя этими динамическими средствами загрузки классов, которые действительно трудно заставить вещи быть быстрыми (потому что класс может быть динамически расширен в любой момент). Кенни Задек, Роджер Гувер и Дэвид Чейз создали действительно быстрый компилятор с собственным кодом для Java без динамической загрузки классов.

В качестве контрпримера, я думаю, что программы на Scheme работали быстрее и использовали меньше памяти, чем программы на Лиспе, которые предшествовали им - отчасти потому, что Гай Стил - и блестящий дизайнер, и блестящий разработчик. (Редкая комбинация, та.)

Но есть что-то в том, что вы говорите: люди, которым не хватает опыта для создания хорошего компилятора с нуля, или которым не хватает опыта для разработки целого языка с нуля, вполне могут взломать реализацию чего-то, не слишком отличающегося от родительского. , В таких случаях вполне вероятно, что получится язык, который не так хорошо разработан, менее хорошо реализован, медленнее и использует больше памяти, чем его предшественник. (Тони Хоар сказал, что Algol 60 улучшил большинство его преемников [sic]).

Верно также и то, что чем позже разработан язык, тем больше вычислительных ресурсов доступно по той же цене. Ранние компиляторы C должны были эффективно работать всего за 128 КБ ОЗУ. Сегодняшние компиляторы C ++ не сталкиваются с такими ограничениями, и у них есть все основания использовать больше памяти: заполнение машины гигабайтами оперативной памяти действительно дешево, а ограничение использования только мегабайтами не экономит ничего; больший объем памяти уже оплачен.

Резюме: Языки возникают потому, что люди хотят улучшить программирование, и у них появляются новые идеи. Языки начинают свое существование, когда кто-то берет целую кучу идей, новых и проверенных, и объединяет их в единое целое. Это большая работа. Один из способов облегчить эту работу - использовать не только проверенные функции , но и проверенные конструкции одного или нескольких языков предшественников. Этот вид дизайна создает впечатление «родительских прав», но фактическое расширение или почти расширение (в случае C ++ - расширение C) встречается редко. Затраты времени и пространства не обязательно увеличиваются по мере развития языков, но часто люди создают языки, делая существующие конструкции более сложными, и чем сложнее дизайн, тем сложнее его реализовать. Поэтому нет ничего необычного в том, что программы, написанные на новом языке, кажутся медленнее или используют больше памяти, чем аналогичные программы, написанные на языке предка. Наконец, как и для всех других форм программного обеспечения, разработанные и созданные недавно компиляторы, как правило, используют больше ОЗУ и ЦП, чем компиляторы, построенные десять лет назад, просто потому, что по бросовым ценам можно купить большое количество циклов ОЗУ и ЦП.

6 голосов
/ 30 апреля 2010

Языки не медленные, Реализации [созданные компиляторами для сборки] являются медленными. Теоретически, у вас может быть интерпретатор C ++, который работает медленнее, чем PHP-компилятор или что-то еще. Языки также не потребляют память, реализации потребляют память.

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

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

3 голосов
/ 30 апреля 2010

Существует большая разница, которая может быть неочевидной, между утверждением, что язык построен на концепциях предшественника, и фактическим созданием его C компилируется в ASM, поэтому он построен на нем, но не обязательно с ним. Часто (чаще всего?) Компиляторы C на самом деле пишутся на C. C ++ построен на C, поддерживает полный спектр C и добавляет к нему кучу вещей. Java - это совершенно другая вещь, аналогично .NET. Они «компилируются» в псевдо-ASM, называемый IL для .NET и ByteCode для Java. Оба требуют некоторого другого шага или VM (виртуальная машина) для запуска.

2 голосов
/ 30 апреля 2010

Каждый язык основан на понятиях другого (языковой дизайн). Каждый новый язык изучает то, что работало на предыдущих языках, а что не работало. Также языки ориентированы на разные группы. Если вы пишете язык для долгосрочного сопровождения и надежности, этот язык, вероятно, не подойдет для сценариев оболочки.

Многие языки тестируют кровати на предмет особенностей или концепций. Они обычно очень гибкие и забавные и могут быть очень быстрыми для написания кода. Одним из них был Basic, как и Perl, Ruby, ...

Другие языки сведены к минимуму и редко меняются - они ориентированы на обратную совместимость и согласованность. Новые функции будут исключены, и, когда они будут добавлены, они будут тщательно проверены перед добавлением в стандарт (да, они, как правило, основаны на стандартах в большей степени, чем предыдущая группа). C, Java, Ada и C ++ были разработаны, чтобы соответствовать здесь. C #, возможно, является кроссовером с добавлением большего количества функций, чем эти другие, но большей стабильностью, чем в предыдущей группе.

Теперь, помимо того, что движет языковыми функциями, существует способ построения языка. Языки часто изначально написаны на другом языке, но не так, как вы предполагаете. В настоящее время Java в основном написана на Java, но JVM, вероятно, представляет собой сборку, написанную вручную, однако вы можете быть уверены, что printf C нигде не найти в Java.

Скомпилированный язык обычно состоит из вашей программы, сокращенной до определенного набора кодов (машинный язык или байт-код), и затем упаковывается с набором подпрограмм (например, System.out.println). Тем не менее, println не просто вызывает println в Си, вместо этого создается библиотека (написанная в некоторой комбинации Java, C, сборка), которая знает, как сделать сам вывод.

В C библиотека будет сгенерирована таким же образом, комбинация C и сборка, которая генерирует код сборки, который может выполнять "printf"

2 голосов
/ 30 апреля 2010

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

На более значимом уровне предыдущие языки могут использоваться повторяющимися способами, которые могут быть упрощены путем добавления некоторого синтаксиса и поведения. Я думаю о том, как можно было бы сделать ООП в C до появления C ++. Или различие между Фортраном с GOTO и Алголом с блочной структурой. Создавать ярлыки было больно, и они могли генерироваться автоматически.

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

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

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

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

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

2 голосов
/ 30 апреля 2010

Языки могут (и часто) написаны с нуля. Но языки могут (и часто делают) основываться на понятиях предшествующих языков. Зачем изобретать велосипед, если у ваших ног лежит идеально круглая?

1 голос
/ 30 апреля 2010

Мне кажется, есть 2 основных способа создания новых языков:

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

2) кто-то разбирающийся в языках программирования решает, что есть проблемы с текущим языком, которые могут быть решены с помощью нового подхода (это может быть радикальное изменение или постепенное изменение ранее). Новый язык разработан с нуля, чтобы быть языком общего назначения. Это может быть описание того, как появился Java или C #.

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

Тогда есть такие языки, как FORTH или APL , которые я просто не могу объяснить ...

0 голосов
/ 30 апреля 2010

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

0 голосов
/ 30 апреля 2010

На самом деле новые языки могут быть намного быстрее. Например, C / C ++ или даже Java могут быть намного быстрее, чем рукописный ассемблер. Go / Haskell / ... который можно легко панелировать, может быть намного быстрее, чем ассемблер на современном оборудовании - что означает, что ассемблерный код "на 25% быстрее", чем сравнивать однопоточную программу на Haskell / Go, если можно включить переключатель, который делает Haskell / Пройдите в 4 раза быстрее (т.е. в 3 раза быстрее, чем оптимизированный ассемблер) на Core Quad, не говоря уже о том, что код гораздо менее глючит?

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

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

  • На основе собственного кода (ассемблер)
  • На основе языка низкого уровня (C, LLVM)
  • На основе кроссплатформенного фреймворка (Java, parrot)
  • Основано на переводчике
  • На основе одноплатформенного фреймворка (.Net - да, я знаю о моно;), но он по-прежнему в основном одноплатформенный)

Например, в Ruby есть Ruby MRI (интерпретатор), JRuby (Java), .Net (IronRuby) и т. Д. Они обычно сильно различаются по скорости. C имеет множество компиляторов и теоретически может иметь интерпретатор. У Haskell есть собственный генератор кода (GHC & co.), Язык низкого уровня (GHC -fvia-c и новый GHC + LLVM) и интерпретатор (ghci).

Языки обычно создаются:

  1. Авторам нравятся языки A и B, поэтому он объединяет их в язык C

  2. У авторов есть совершенно новая идея (например, объекты, типизирование утки), которая не может быть выражена на существующих языках / новая идиома, которая не может быть выражена как хорошая на существующих языках, поэтому они создают новый язык, который представляет собой совершенно новую функцию.

  3. Авторы считают какую-то особенность ужасной и хотят от нее избавиться (по любым причинам). Как enum в старой Java.

В первом и третьем случае новый язык «наследует» один или несколько языков (обычно много). Но обычно это их комбинация.

0 голосов
/ 30 апреля 2010

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

...