Необов’язкові крапки з комою


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 насправді знаходиться в таборі "термінаторів виписки" (оскільки для реалізації потрібно зробити висновок з комою до }або в кінці файлу).
ruakh

Так, абсолютно залежить від мови. Моя особиста здогадка - це те, що крапки з комою є лише різновидом загальнозгодженої конвенції, якої дотримуються більшість мовних дизайнерів. Принаймні, це має певний сенс з більш природно схожої мови. До речі, те ж саме і для {and} для блоків: вони використовуються багатьма мовами, однак не всі, і ви насправді не повинні цього робити. Не існує універсальної причини для цього.
JensG

Відповіді:


24

Якщо зробити їх обов'язковими (або повністю заборонити їх), зменшується кількість кутових випадків, усувається потенційне джерело неясних помилок і спрощується конструкція компілятора / інтерпретатора.

Мовні дизайнери, які вирішили зробити їх необов'язковими, вирішили жити з неоднозначністю взамін на більшу синтаксичну гнучкість.


7
@RobertHarvey Єретик! Повинно бути один, очевидний спосіб зробити це і лише один. Між іншим, існує лише один спосіб зробити це в perl.

1
BTW - деякі мови мають загальну кількість надмірності в граматиках, тому зробити крапку з комою необов’язковою на практиці є лише іноді неоднозначною. Це означає, що я вважаю, що крапка з комою - це неправильний біт надмірності для падіння - мені дуже подобається Haskell, де ви замість цього ви кидаєте паролі та коми. Гаразд, ви можете кинути крапку з комою також у Haskell, але це насправді не те саме, що Javascript.
Steve314

2
Проблема IIRC полягає в тому, що вони не відповідають формальній моделі, але те, що генератори аналізаторів не видають хороших повідомлень про помилки. Тобто вони мають обмежені знання про поширені помилки, тоді як рукописний аналізатор може отримати набагато корисніше повідомлення про помилку. Наприклад, Gcc використовується для використання зубрів для граматики C. Аналогічно, проблема полягає в тому, що "крайові випадки" - це не формальні крайові випадки, а м'які - тобто для парсера AST зрозумілий, а для людини AST "зрозумілий", але вони не згодні з тим, що таке AST.
Мацей П'єхотка

2
@Maciej Piechotka - Я не мав на увазі, що пареси в Хаскеллі необов’язкові. Я говорю про те, щоб відмовитись від зайвого як рішення дизайну мови. Справа в тому, що ви не використовуєте паролі чи коми для виклику функції в Haskell. Ви можете передавати кортеж як аргумент, але це все ще синтаксис кортежу, а не для передачі аргументів. Haskell (і ML та інші) "скинули" паролі і коми для аргументів функції в тому сенсі, що існує ця загальна конвенція в інших мовах (починаючи з Algol?), Але Haskell цього не робить.
Steve314

1
@Maciej Piechotka - Звичайно, це взагалі ніколи не було універсальною конвенцією - лише тому, що мови сімейства Алголя це не означає, що інші мови визначають себе відносно цього, тому моє "упущене" твердження є неправильним у цьому сенсі - але з усім мови сімейства С в наші дні це відчуває трохи так.
Steve314

15

JavaScript показав нам, що це дуже погана ідея. Наприклад:

return
0;

В C це повертає значення 0. У JavaScript це повертається undefinedчерез те, що крапка з комою вставляється після оператора return, і не відразу зрозуміло, чому ваш код ламається, якщо вам не відомо про деталі автоматичної вставки крапки з комою.


1
@delnan: Python не розроблений так, щоб бути схожим на C. Це добре відомо на основі відступів і, таким чином, дуже орієнтовано на лінійку, і йому не потрібні крапки з комою. JavaScript технічно цього вимагає; це вставлення одного, коли він знаходить одне відсутнє, що перетворює те, що схоже на один синтаксично вірний вислів, у два різних твердження з абсолютно різною семантикою.
Мейсон Уілер

7
Це не погана ідея, вона просто заплутує людей, які намагаються використовувати JavaScript, не намагаючись дізнатися про її автоматичну вставку з комою . Можливо, замість того, щоб сказати "це дуже погана ідея", ви могли б точніше сказати, "якщо крапки з комою необов'язково вводять підводні камені для програмістів, які не виходять і дізнаються всі деталі".
TehShrike

4
@delnan: Дивна причина: JavaScript зазвичай не вставляє крапку з комою в кінці рядка, за винятком виправлення недійсної програми. Після 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, це викликало менше занепокоєння.
Шон Максоміт

3

Крапки з комою корисні в граматиці з 2 причин. По-перше, це дозволяє розділити довгі висловлювання на кілька рядків, не маючи богатих символів продовження (я говорю про вас, 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 принаймні є гідно вибрані маркери продовження лінії (& та _ відповідно). Для чистого "" OMG, що вони думали ", FoxPro нічого не перемагає. Щоб продовжити рядок, ви використали крапку з комою.
DougM

2

Точки з крапкою з комою - це не завжди все, або нічого, як ви згадуєте у своєму запитанні. Наприклад, граматика Луа ретельно розроблена як вільна форма (всі пробіли, включаючи нові рядки, можна ігнорувати), але також без необхідності використовувати крапки з комою. Наприклад, такі програми еквівалентні:

--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

0

Не дивлячись на все, що стосується дизайну та будівництва, я вважаю, що багато програмістів походять з різного походження, а деякі навчились використовувати напівкрапку, а деякі - ні. Багато нових мов, які з'являються, не потребують напівкрапки, але все ж дозволяють йому існувати. Я думаю, що це може бути просто спосіб отримати більше програмістів, щоб навчитися кодувати на цих нових мовах, не відмовляючись від своїх звичок з моменту їх початку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.