История конечных запятых в грамматиках языков программирования

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

В качестве примера ниже приведена совершенно допустимая инициализация массива в Java (Инициализаторы массивов JLS 10.6):

int[] a = { 1, 2, 3, };

Мне любопытно, знает ли кто-нибудь, какой язык первым разрешил такие запятые в конце. Судя по всему, это было у C еще в 1985 году.

Кроме того, если кто-то знает другие грамматические «особенности» современных языков программирования, мне было бы очень интересно услышать о них. Я читал, что Perl и Python, например, даже более либеральны, разрешая запятые в конце своей грамматики.


person polygenelubricants    schedule 22.02.2010    source источник
comment
Если я помню, когда я изучал C из оригинального K&R (pre-ANSI) в 1983 году, конечные запятые были разрешены. Это было сделано намеренно, чтобы упростить автоматическую генерацию кода (такими инструментами, как YACC).   -  person Ralph    schedule 10.09.2011
comment
Это также помогает, когда (как в определении enum) каждый элемент находится в отдельной строке: добавление нового значения в конце является просто дополнительной строкой (не требующей изменения новой предпоследней строки), что потенциально позволяет избежать зависимости от / за счет любые изменения в новой предпоследней строке.   -  person jhfrontz    schedule 15.02.2018


Ответы (4)


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

В более поздних языках программирования в стиле Паскаля (C, Modula-2, Ada и т. Д.) Были написаны стандарты, позволяющие принимать нечетную дополнительную точку с запятой, не ведя себя так, как будто вы просто пописали в смесь торта.

person T.E.D.    schedule 22.02.2010
comment
Говоря о точках с запятой, мне было бы интересно увидеть диаграмму частоты использования точек с запятой в истории человечества. Согласно Википедии, самое раннее общее использование относится к 1591 году. Я подозреваю, что с каждым новым изобретенным языком программирования в стиле фигурных скобок наблюдается скачок в его использовании. Вероятно, также будет шишка, когда люди поймут, что с ее помощью можно подмигивать людям ;) - person polygenelubricants; 22.02.2010
comment
Шутки в сторону; Я не думаю, что это повлияло на частоту их использования; - person Aiden Bell; 22.02.2010
comment
Интересно отметить, что в BASIC двоеточие используется гораздо чаще, чем точка с запятой, а в Commodore Vic-20 и его производных (C64, C128 и т. Д.) Средний ряд заканчивается на J, K, L, двоеточие ( вместо J, K, L, точка с запятой). - person supercat; 27.10.2011
comment
Вы можете найти фон для C здесь - person Shafik Yaghmour; 18.03.2015

Я только что узнал, что компилятор Fortran g77 имеет -fugly-comma Ugly Null Arguments, хотя он немного отличается (и, как следует из названия, довольно некрасиво).

Параметр -fugly-comma позволяет использовать одну конечную запятую для обозначения «передать дополнительный конечный нулевой аргумент» в списке фактических аргументов внешней процедуре и использовать пустой список аргументов для такой процедуры, чтобы означать «передать один нулевой аргумент. аргумент ».

Например, CALL FOO(,) означает «передать два нулевых аргумента», а не «передать один нулевой аргумент». Кроме того, CALL BAR() означает «передать один нулевой аргумент».

Однако я не уверен, на какой версии языка он появился впервые.

person polygenelubricants    schedule 22.02.2010
comment
Это вариант-тип-f: уродливая-запятая, или это просто ускользающая запятая. Я действительно хочу верить, что это последнее. - person Conspicuous Compiler; 23.02.2010

[Кто-нибудь знает] другие грамматические «особенности» современных языков программирования?

Один из моих любимых, Modula-3, был разработан в 1990 году с благословения Никлауса Вирта в качестве последнего на тот момент языка в «Семья Паскаля». Кто-нибудь еще помнит те ужасные споры о том, где точка с запятой должна быть разделителем или терминатором? В Modula-3 выбор за вами! EBNF для последовательности утверждений:

stmt ::= BEGIN [stmt {; stmt} [;]] END

Точно так же при написании альтернатив в операторе CASE Modula-3 позволяет использовать вертикальную черту | как разделитель или префикс. Чтобы вы могли написать

CASE c OF
| 'a', 'e', 'i', 'o', 'u' => RETURN Char.Vowel
| 'y' => RETURN Char.Semivowel
ELSE RETURN Char.Consonant
END

или вы можете оставить начальную полосу, возможно, потому что вы предпочитаете писать OF в этой позиции.

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


P.S. Objective Caml допускает разрешающее использование | в выражениях case, тогда как более ранний и тесно связанный диалект Standard ML - нет. В результате выражения case в стандартном коде машинного обучения часто выглядят более уродливыми.


РЕДАКТИРОВАТЬ: увидев ответ T.E.D., я проверил грамматику Modula-2, и он верен, Modula-2 также поддерживает точку с запятой в качестве терминатора, но через устройство пустого оператора, что делает такие вещи, как

x := x + 1;;;;;; RETURN x

юридический. Полагаю, это неплохо. Однако Modula-2 не позволяла гибко использовать разделитель регистра |; который, кажется, произошел от Модулы-3.

person Norman Ramsey    schedule 23.02.2010
comment
Верно. Я считаю, что именно так C решил проблему. Решение Ada ближе к Modula-3, так что уродливое использование нескольких точек с запятой не было бы законным. Если вам нужен пустой оператор по какой-то странной причине в Аде, вы должны сказать null; - person T.E.D.; 23.02.2010
comment
Использование точки с запятой в качестве пустого оператора недопустимо в классическом Modula-2 Вирта, оно было добавлено в ISO Modula-2 после долгих споров, и не всем это понравилось. Modula-2 R10 придерживается подхода Вирта, но добавляет встроенную фиктивную процедуру под названием TODO, которая принимает символьный литерал в качестве аргумента, который печатается как предупреждение времени компиляции в режиме DEBUG или ошибка в режиме производственной сборки. - person trijezdci; 29.09.2015

Что меня всегда раздражало в C, так это то, что, хотя он допускает дополнительную конечную запятую в списке intializer, он не допускает дополнительную конечную запятую в перечислителе. список (для определения литералов перечислимого типа). Эта небольшая непоследовательность кусала меня за задницу больше раз, чем я хотел бы признаться. И без причины!

person Norman Ramsey    schedule 23.02.2010
comment
Я думаю, что вы отстали в этом. Я думаю, что причина заключалась в том, что наличие дополнительного элемента в конце определения перечисления ни на что не повлияет (если его имя не совпадает с другим идентификатором), тогда как добавление дополнительного элемента в конце инициализатора может повлиять на размер выделенный массив. - person supercat; 27.10.2011
comment
Завершающая запятая в списках перечислений была исправлена ​​в стандарте C99, который был выпущен за 11 лет до того, как был написан этот ответ. Это известная и исправленная языковая ошибка. - person Lundin; 30.06.2020
comment
Между тем C ++ допускает конечные запятые как для списков инициализаторов, так и для списков перечислений, но непоследовательно, не для списков инициализаторов членов конструктора (в любом случае, начиная с C ++ 20). - person Dwayne Robinson; 11.05.2021