Необязательные точки с запятой

10

Чаще всего в императивном языке общего назначения точки с запятой в качестве разделителей операторов либо обязательны, либо полностью запрещены (например, C и Python).

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

Какие дизайнерские решения стоят за этим? Я понимаю, что точки с запятой необходимы при написании нескольких операторов в одной строке, но есть ли еще одна причина сделать их обязательными (за исключением следующего C)?

Абер Клед
источник
1
Вам нужно подумать о терминаторах операторов (perl, c) и разделителях операторов (javascript, pascal).
5
В Python точки с запятой могут использоваться для разделения нескольких операторов в одной строке. А поскольку разрешен «пустой» оператор, точки с запятой могут использоваться в конце большинства операторов.
Грег Хьюгилл
1
I understand that semicolons are essential when writing multiple statements on the same line- Зависит от языка. Мой любимый не имеет таких разделителей вообще, следующий оператор начинается, когда все аргументы функции были использованы.
Изката
1
@MichaelT: Я не думаю, что ваша классификация верна: Perl, вероятно, принадлежит к обеим группам, и JavaScript фактически находится в лагере «терминаторов операторов» (поскольку реализации необходимы для вывода точки с запятой до }или в конце файла).
Руах
Да, абсолютно зависит от языка. Мое личное предположение состоит в том, что точки с запятой - это просто некая общепринятая договоренность, которой придерживается большинство разработчиков языков. По крайней мере, это имеет некоторый смысл с более естественной языковой точки зрения. Кстати, то же самое с {и} для блоков: они используются во многих языках, но не во всех, и вам на самом деле не нужно это делать. За этим нет универсальной причины.
JensG

Ответы:

24

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

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

Роберт Харви
источник
7
@RobertHarvey Еретик! Должен быть один, очевидный способ сделать это и только один. Кстати, в Perl есть только один способ сделать это.
1
Кстати, некоторые языки в целом имеют достаточную избыточность в грамматике, поэтому использование точки с запятой необязательно только на практике неоднозначно. Тем не менее, я думаю, что точка с запятой - это неправильная часть избыточности, которую нужно отбрасывать - мне очень нравится Haskell, где вместо аргументов вместо парней ставятся запятые и запятые. Хорошо, вы можете удалить точку с запятой в Haskell, но это не то же самое, что Javascript.
Steve314
2
Проблема IIRC в том, что они не соответствуют формальной модели, но генераторы парсера не выдают хороших сообщений об ошибках. Т.е. они имеют ограниченные знания об общих ошибках, тогда как рукописный парсер может получить гораздо более полезное сообщение об ошибке. Gcc, например, используется для использования бизона для грамматики Си. Точно так же проблема заключается в том, что «крайние случаи» - это не формальные крайние случаи, а мягкие - то есть для анализатора AST ясна, а для человека AST «ясна», но они не согласны с тем, что такое AST.
Maciej Piechotka
2
@Maciej Piechotka - я не имел в виду, что в Хаскеле пареноны были необязательными. Я говорю об отбрасывании чего-то лишнего в качестве решения для языкового дизайна Суть в том, что вы не используете парень или запятую для вызова функции в Haskell. Вы можете передать кортеж в качестве аргумента, но это все еще синтаксис для кортежа, а не для передачи аргументов. Haskell (и ML, и другие) «отбрасывают» парены и запятые для аргументов функций в том смысле, что в других языках существует это общее соглашение (начиная с Algol?), Но Haskell этого не делает.
Steve314
1
@Maciej Piechotka - Конечно, в любом случае это никогда не было действительно универсальным соглашением - просто потому, что языки семейства Algol делают это, это не означает, что другие языки определяют себя относительно этого, поэтому мое «отброшенное» утверждение неверно в этом смысле - но со всеми языки C-семьи в наши дни кажутся такими.
Steve314
15

JavaScript показал нам, что это очень плохая идея. Например:

return
0;

В C это возвращает значение 0. В JavaScript это возвращается, undefinedпотому что точка с запятой вставляется после оператора return, и не сразу понятно, почему ваш код ломается, если вы случайно не узнали о деталях автоматической вставки точки с запятой.

Мейсон Уилер
источник
1
@delnan: Python не предназначен для того, чтобы выглядеть как C. Он хорошо известен как основанный на отступах и, следовательно, сильно ориентированный на строки, и ему не нужны точки с запятой. JavaScript технически делает требовать от них; он вставляет один, когда находит один отсутствующий, который преобразует то, что выглядит как один синтаксически допустимый оператор, в два разных оператора с совершенно другой семантикой.
Мейсон Уилер
7
Это не плохая идея, это просто сбивает с толку людей, которые пытаются использовать JavaScript, не удосужившись узнать о его автоматической вставке точек с запятой . Возможно, вместо того, чтобы сказать «это очень плохая идея», вы могли бы более точно сказать, что «сделать точку с запятой необязательной, вы увидите ловушки для программистов, которые не выходят и не изучают все детали».
TehShrike
4
@delnan: Причина, по которой это удивительно, заключается в том, что JavaScript обычно не вставляет точку с запятой в конце строки, за исключением того, чтобы исправить в противном случае недействительную программу. After return- это один из немногих случаев, когда JavaScript вставляет точку с запятой, даже если программа будет работать без нее. (Но, конечно, это подрывает точку зрения Мейсона Уилера. Проблема не в том, что точки с запятой необязательны, а в том, что правила несовместимы.)
ruakh
6
@TehShrike: Создание необязательных точек с запятой вводит ловушки для всех программистов, потому что оно произвольно интерпретирует опечатки вместо того, чтобы спрашивать вас, что вы имели в виду. Каждый делает опечатку время от времени.
Ян Худек
1
JavaScript показал, что его реализация необязательных точек с запятой имеет недостатки. Это не показывает, что необязательные точки с запятой сами по себе плохие.
CodesInChaos
4

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

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

Например, попробуйте вставить точку с запятой в следующую серию операторов C.

functionCall(3, 4) 9 + (3 / 8) variable++ while(1) { printf("Hello, world\n") }

Хотя есть некоторые странные вещи, которые вы больше не можете делать, например while(1);, по большей части, с помощью современных методов синтаксического анализа относительно легко определить, где заканчиваются операторы без определенного разделителя. Даже если вы все еще хотите разрешить странные вещи, не так сложно сделать newline_or_semicolonнетерминал.

Карл Билефельдт
источник
Когда C был первоначально разработан в начале 1970-х годов, для упрощения компиляторов требовались терминаторы операторов. К середине 90-х годов, когда был разработан Javascript, это стало меньше беспокоить.
Шон МакSomething
3

Точки с запятой полезны в грамматике по двум причинам. Во-первых, он позволяет разбивать длинные операторы на несколько строк без чертовых символов продолжения (я говорю о вас, Fortran и Basic). Во-вторых, это дает парсеру возможность «отказаться» от синтаксического анализа, когда синтаксис становится действительно запутанным из-за опечатки. Кража по примеру Карла Билефельда,

functionCall(3, 4) 9 + (3 / 8) variable++ while(1) { printf("Hello, world\n") }

представьте, что вы набрали еще одного открытого парена:

functionCall((3, 4) 9 + (3 / 8) variable++ while(1) { printf("Hello, world\n") }

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

functionCall((3, 4);  <- something is wrong here. emit error and keep going.
                      9 + (3 / 8); variable++; while(1) { printf("Hello, world\n"); }

Теперь синтаксическому анализатору легче сообщать об ошибке и легче найти строку / столбец, где она произошла.

Марк Лаката
источник
1
Fortran и Basic, по крайней мере, имеют прилично выбранные маркеры продолжения строки (& и _ соответственно). Ибо «О Боже, о чем они думали», ничто не сравнится с FoxPro. Чтобы продолжить линию, вы использовали точку с запятой.
DougM
2

Точки с запятой не всегда полностью или ничего, как вы упоминаете в своем вопросе. Например, грамматика Lua тщательно разработана, чтобы иметь произвольную форму (все пробелы, включая символы новой строки, могут быть проигнорированы), но также без необходимости использовать любые точки с запятой. Например, следующие программы эквивалентны:

--One statement per line
x = 1
y = 2

--Multiple statements per line
x = 1 y = 2

--You can add semicolons if you want but its just for clarity:
x = 1; y = 2
hugomg
источник
0

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

HeadphoneHaxZ
источник