Зависит ли синтаксис языков программирования от их реализации?

12

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

Интерпретируемые (байтово-интерпретируемые?) Языки, такие как Python, Lua и т. Д., Обычно имеют чрезвычайно мягкий и простой синтаксис и, как правило, не содержат типов или не требуют от разработчика явного написания типов переменных в исходном коде;

Скомпилированные языки, такие как C, C ++, Pascal и т. Д., Обычно имеют строгий синтаксис, обычно имеют типы и в основном требуют больше времени на разработку кода

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

Некоторые из более современных скомпилированных языков программирования, такие как D и Vala (и реализация Java GNU GJC), возможно, являются исключением из этого правила и напоминают синтаксис и функции языков JIT-Compiled, таких как Java и C #.

Мой первый вопрос: действительно ли это актуально? Или это просто совпадение, что большинство интерпретируемых языков имеют простой синтаксис, JIT-компилированные имеют умеренный синтаксис и функции и т. Д.

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

ApprenticeHacker
источник
@YannisRizos извините, это не цитата. Я просто хотел выделить это. Я отредактирую это.
ApprenticeHacker
1
Круто, я думал, что это не цитата, но это может привести к тому, что ответчики подумают, что это так, и не будут пытаться опровергнуть это (или слепо согласиться с этим) ... Я заметил схожие закономерности, но, к сожалению, ничего хорошего ответ.
Яннис
@ R.MartinhoFernandes извините, я не знал об этом. Я отредактирую это (снова).
ApprenticeHacker
4
Perl динамически типизируется для пользовательских типов, статически типизируется в отношении различающихся массивов, хэшей, скаляров и подпрограмм и строго типизируется с использованием строгой интерпретации и JIT-компиляции (не в одно и то же время, разумеется) ... Всякий раз, когда кто-то пытается чтобы понять смысл языкового дизайна,
добавление
3
Что вы подразумеваете под «мягким синтаксисом» против «строгого синтаксиса»? Все они формальные языки, и ни один из них не запускает исходный код с синтаксическими ошибками.
nikie

Ответы:

17

Между семантикой и синтаксисом нет никакой связи. Homoiconic скомпилированные языки, такие как Scheme, имеют довольно минималистичный синтаксис. Низкоуровневые скомпилированные мета-языки, такие как Forth, еще проще. Некоторые очень строго типизированные скомпилированные языки построены на тривиальном синтаксисе (например, ML, Haskell). OTOH, синтаксис Python очень тяжелый, с точки зрения ряда правил синтаксиса.

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

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

SK-логика
источник
+1 за то, что заставил меня посмотреть "гомиконик" ... И за тонкий поклон PHP ...
Яннис
1
+1, языки, которые развивались слишком долго и не содержали никаких конструктивных гарантий , относится ли это также к Delphi / Object-Pascal?
ApprenticeHacker
1
@ThomasEding, ты не прав. Та же самая семантика может быть реализована поверх очень широкого диапазона синтаксических стилей, даже с языком без синтаксиса (таким как Lisp или Forth). Один и тот же синтаксис может использоваться с очень разнообразными семантиками - например, синтаксис выражений C и Verilog практически одинаков, но семантика существенно отличается.
SK-logic
1
@ SK-logic - То, что он сложен и завершен по Тьюрингу, не означает, что он не является, по крайней мере, очень большой частью синтаксиса программы. Разбор различных языков является полным по Тьюрингу, который магическим образом не делает разбор чего-либо, что «не имеет ничего общего с синтаксисом». Синтаксис не о «сфере действия», а о правилах структуры утверждений в языке - ничего не говоря о том, что означают эти утверждения. Проверка типов и вывод типов работают с синтаксическими деревьями программ, не выполняя их - они определяют вещи со структурой программы, ничего не говоря о ...
Джек,
1
@ Джек, ты пытаешься переопределить синтаксис. Нет практических языков, нуждающихся в синтаксическом анализаторе Turing, большинство из них не более чем контекстно-свободные. И это где синтаксис должен остаться. Пожалуйста, не распространяйте это (уже слишком растянутое) понятие где-либо еще. И я уже упоминал об изоморфизме Карри-Говарда - это все о семантике, далеко за пределами простых правил корректности. Я думаю, что сам термин « type checking» чрезвычайно контрпродуктивен и не должен использоваться, он очень вводит в заблуждение, он не отражает природу систем типов.
SK-logic
6

В основном это совпадение.

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

Синтаксис языка действительно оказывает влияние - например, Паскаль был очень тщательно спроектирован, чтобы он мог использовать однопроходный компилятор - то есть один проход по исходному тексту, и у вас есть исполняемый машинный код. Ада, с другой стороны, не обратила на это никакого внимания, а компиляторы Ады, как известно, трудны для написания - большинству требуется более одного прохода. (Один очень хороший компилятор Ada, который я использовал много лет назад, был 8-проходным компилятором. Как вы можете себе представить, он был очень медленным.)

Если вы посмотрите на старые языки, такие как Fortran (скомпилированный) и BASIC (интерпретированный или скомпилированный), у них / был очень строгий синтаксис и семантические правила. [В случае с Бейсиком, то есть не со старым Бейсиком Билла, вам нужно вернуться к этому оригиналу.]

С другой стороны, при взгляде на другие более старые вещи, такие как APL (куча веселья), это была своего рода динамическая типизация. Это также обычно интерпретировалось, но также могло быть скомпилировано.

Сложный синтаксис сложен - если это означает, что у вас есть вещи, которые являются необязательными или могут быть выведены, то это означает, что язык обладает достаточным богатством, чтобы его можно было отбраковать. Опять же, у BASIC было это много лет назад, когда утверждение «LET» стало необязательным!

Многие из идей, которые вы сейчас видите (например, типизирование или динамическая типизация), на самом деле очень старые - впервые появились в 1970-х или в начале 1980-х годов. То, как они используются, и языки, на которых эти идеи используются, изменилось и выросло. Но по сути, многое из того, что нового, на самом деле - это старые вещи, одетые в новую одежду.

Вот несколько примеров из головы:

  • APL: динамическая типизация. Обычно интерпретируется. Пришел с 1960-х / 1970-х годов.
  • ОСНОВНАЯ: сильная или динамическая типизация. Интерпретируется или компилируется. 1970-е и многие другие.
  • Фортран: сильная типизация. Составитель. 1960-е или раньше.
  • Алгол68: сильная типизация. Составитель. 1960-х годов.
  • PL / 1: строгая типизация. Составитель. 1960-х годов.
  • Паскаль: сильная типизация. Составитель. 1970-х. (Но в 1980-х были компиляторы P-System, очень похожие на компиляторы JIT!)
  • Некоторые реализации Fortran и других DEC в первые дни были частично скомпилированы и частично интерпретированы.
  • Smalltalk: динамическая типизация. Скомпилировано в байт-код, который интерпретируется. 1980-х.
  • Пролог: больше странностей. Функциональная. Скомпилировано (Turbo Prolog, кто-нибудь?). 1980-х.
  • C: сильный (ха-ха) типирование. Составитель. 1960's..today.
  • Ада: супер-сильная типизация. Составитель. 1980-х.
  • Perl: динамическая типизация. (Сильный синтаксис). Интерпретированный. 1990-е (?).

Я мог бы продолжить.

  • Уголок Nitpickers: Многие интерпретируемые языки токенизируются или «скомпилированы в байты» во время загрузки / чтения исходного кода. Это значительно упрощает последующую работу интерпретатора. Иногда вы можете сохранить скомпилированную версию кода. Иногда ты не можешь. Его все еще интерпретируют.

Обновление: потому что я не был достаточно ясен.

Набор текста может широко варьироваться.

Фиксированная статическая типизация во время компиляции распространена (например, C, Ada, C ++, Fortan и т. Д.). Это где вы объявляете вещь типа, и так всегда.

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

И затем есть свободная типизация, например PHP, где вы можете делать действительно странные вещи, такие как присвоение числового целого числа (в кавычках, то есть строки) переменной, а затем добавление к ней числа. (например, «5» + 5 приведет к 10). Это земля странного, но иногда очень и очень полезного.

ОДНАКО это функции, разработанные на языке. Реализация просто делает это возможным.

quickly_now
источник
13
Строгая типизация не является аналогом динамической типизации. Это аналог слабой типизации. Аналогом динамической типизации является статическая типизация: в одном из них типы выражений в программе могут быть известны статически (т.е. без запуска программы); в другом типы могут быть известны только динамически (т.е. программа должна быть запущена).
Р. Мартиньо Фернандес
Да, и оба варианта BASIC и APL делали это еще в конце 1970-х годов. Типы APL не совсем такие, какими мы их понимаем сегодня (такие вещи, как универсально типизированные целые числа / числа с плавающей точкой, но также могут быть векторами, строками и многомерными матрицами).
quick_now
Интерпретатор Фортрана все еще широко используется (см. Cernlib и PAW). И его потомок, ROOT, построен на интерпретаторе C ++.
SK-logic
Я не совсем понимаю, как строгая / слабая и статическая / динамическая типизация относятся к синтаксису, если честно. Но качество ответа было довольно хорошим, поэтому я просто избегаю голосования. Я бы классифицировал типизацию C как «статическую / слабую» (тривиально смотреть на сохраненное значение, как если бы это был другой тип, возможно, получая неверное значение).
Ватин
@Vatine - я бы сказал, что сильный во время компиляции, несуществующий во время выполнения - если вы хотите так. Вы можете сделать это, используя указатели и их эквиваленты на многих языках. Это возможно даже в классическом паскале с использованием вариантов записи, а в Ada - с помощью UNCHECKED_CONVERSION (хотя это сложно, это возможно).
quick_now
2

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

StackedCrooked
источник
@IntermediateHacker: но это в Java, так что я должен быть потрясающим
сех
2

Я в целом согласен с fast_now в том, что ваши наблюдения в основном являются результатом истории. Тем не менее, основные рассуждения сводятся к чему-то вроде этого:

The more modern a language is, the more comfortable it should be to use.

(На самом деле это не цитата, а моя собственная формулировка.) Когда я пишу comfortableздесь, я имею в виду то, что вы назвали best features of both. Точнее, я не хочу говорить за или против статической / динамической типизации или строгого / мягкого синтаксиса. Вместо этого важно видеть, что основное внимание уделяется разработчикам и повышению их уровня комфорта при работе с языком.

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

  • У нас есть сотни языков программирования в эти дни. Когда появляется новый, как он может найти широкую аудиторию? Это главная причина, почему новые языки всегда пытаются повысить уровень комфорта разработчиков. Если язык может сделать то же самое, что и старый, но может сделать это намного проще / проще / элегантнее / и т.д. Вы можете рассмотреть возможность переключения.

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

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

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

  1. Начальная стадия: это крутая вещь, которую нужно иметь, но передовая технология едва заставляет ее работать за счет комфорта / удобства использования / что-нет.
  2. Технологическое усовершенствование: мы можем построить эти вещи более надежно, быстрее и проще.
  3. Ориентация на пользователя: аналогично движению Web2.0, ориентированному на взаимодействие с пользователем, новые языки программирования ориентированы на разработчиков.
Фрэнк
источник
(Not a quote really, just my own formulation.)Ну, вы отформатировали его как код, а не как цитату, так что я не думаю, что кто-то думал, что это цитата :)
yannis
3
Комфорт явно зависит от вкуса (который всегда полностью субъективен). Язык, на котором я чувствую себя наиболее комфортно, был разработан в 1959 году, и я терпеть не могу иметь дело с некоторыми языками, появившимися в этом столетии.
SK-logic
1
Комфорт также зависит от цели. Запуск PHP или Prolog на встроенном 8-тысячном микро-контроллере для контроллера стиральной машины может быть «удобным» для программирования, но также и чертовски сложным, чтобы он действительно работал и работал с приемлемой производительностью.
quick_now
0

Данный язык программирования может или не может предоставлять или ограничивать достаточную семантическую информацию для компилятора, чтобы определить, как преобразовать его в исполняемый код без добавления решений времени выполнения («какой тип это переменная?» И т. Д.). Некоторые языки явно предназначены для это ограничение обязательно, или его легко определить.

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

Однако языки, в которых код (evalString ()) может быть создан или введен во время выполнения (и другие вещи, которые компилятор не может вывести или угадать), могут требовать, чтобы интерпретатор или JIT-компилятор были доступны во время выполнения, даже при попытках предварительно скомпилируйте их.

В прошлом язык программирования и его реализация могли развиваться так, чтобы соответствовать некоторым аппаратным ограничениям, таким как, может ли интерпретатор соответствовать 4k или 16k, или компилятор мог завершить работу менее чем за минуту процессорного времени. Поскольку машины становятся быстрее, стало возможным (пере) компилировать некоторые ранее интерпретированные программы так быстро, как программист может нажать клавишу возврата или интерпретировать ранее скомпилированный исходный код программы быстрее, чем чуть более старое оборудование может запускать оптимизированные скомпилированные исполняемые файлы.

hotpaw2
источник