Почему большинство языков программирования не вкладывают блочные комментарии?

18

Насколько я знаю, некоторые делают, но не самые популярные. Есть ли что-то плохое во вложении комментариев?

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

амара
источник
Вот несколько ответов: о, это имеет смысл =) Я полностью делаю вложенные блочные комментарии; хотя у меня есть отдельная стадия лексизма, это не описанная ограничивающая логика SK.
@Vuntic: Если у вас есть отдельная стадия лексизма, в которой используются вещи более сложные, чем регулярные выражения, у вас могут возникнуть проблемы с производительностью. RE являются быстрыми и простыми в использовании благодаря внедрению DFA.
Дэвид Торнли
Он ловит больше ошибок раньше, чтобы не допустить вложения
4
@ Дэвид: ... совсем нет. Это на самом деле очень быстро.
Амара
Я хотел бы предложить, чтобы, если вы хотите разрешить вложенные комментарии, вы разрешаете помечать теги начального комментария токеном и требовать, чтобы, если тег начального комментария, таким образом, отмечался, его тег конечного комментария был отмечен одинаково. Это позволило бы быстро идентифицировать несбалансированные начальные / конечные теги и избежать ошибок, вызванных необнаруженными несбалансированными тегами.
суперкат

Ответы:

6

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

Во-первых, давайте согласимся, что единственный раз, когда «вложение» или «не вложение» видимо программисту, это когда программист пишет что-то структурно подобное:

do_something();
/* comment /* nested comment */ more comment */
do_something_else();

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

do_something();  /* do a thing */
/* [ajo] 2017-12-03 this turned out to be unnecessary
do_something_else(); /* do another thing */
*/

И это плохо. Это не образец, который мы (как языковые дизайнеры) хотим поощрять! Правильный способ написания фрагмента коды выше:

do_something();  /* do a thing */

Этот «неправильный» код, этот фальстарт или что бы то ни было, не входит в кодовую базу. Это относится, в лучшем случае, к истории контроля версий. В идеале, вы бы никогда не написали неправильный код для начала, не так ли? И если неправильный код служил цели там, предупреждая сопровождающих не восстанавливать его по какой-то причине, ну, это, вероятно, работа для хорошо написанного и намеренного комментария кода. Попытка выразить «не делай X», просто оставив в некотором старом коде, который делает X, но закомментирован, не самый читаемый или эффективный способ помешать людям делать X.

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

Перед тем, как задать вопрос: да, такие языки, как C, C # и C ++ уже дают программисту еще один инструмент для «закомментировать» большие блоки кода: #if 0. Но это всего лишь частное применение препроцессора C, который сам по себе является большим и полезным инструментом. На самом деле для языка было бы крайне сложно и специально для него поддерживать условную компиляцию, #ifно не поддерживать ее #if 0.


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

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

В случае вложенных комментариев, все остальное является равным - вы можете смело игнорировать низко проголосовал ответы , которые утверждают , что разбор вложенные /*будет каким - то образом быть «трудным» для синтаксического анализа. (Вложенные /*не сложнее, чем вложенные (, с которыми почти каждый парсер в мире уже должен обращаться.)

Итак, при прочих равных, должен ли языковой дизайнер упростить вложение комментариев (т. Е. Комментировать код) или это сложно? Напомним, что комментирование кода - плохая вещь.

QED


Сноска. Обратите внимание, что если вы не разрешите вложенные комментарии, то

hello /* foo*/bar.txt */ world

вводящий в заблуждение «комментарий» - это эквивалентно

hello bar.txt */ world

(что, вероятно, является синтаксической ошибкой). Но если вы делаете разрешить вложенные комментарии, то

hello /* foo/*.txt */ world

вводящий в заблуждение «комментарий» - это эквивалентно

hello

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

Quuxplusone
источник
1
У меня другое мнение, основанное на простом факте - я не все видел (как и вы). Поэтому, хотя эти золотые правила, такие как «Не комментируйте код», выглядят красиво, у жизни есть свои пути. В этом конкретном случае я делаю это очень часто в качестве переключателя, когда я тестирую какую-то новую функцию и мне нужно постепенно вводить некоторый код, поэтому я закомментирую код, затем меньше, меньше, меньше, и, наконец, у меня есть рабочая часть, и я Можно удалить все комментарии (по коду). Мой идеальный язык, конечно, будет поддерживать вложенные комментарии :-).
Greenoldman
@greenoldman: большинство языков не имеют вложенных комментариев, но у них будет некоторая реальная функция «удалить блок кода», которая используется реже, чем «оставить комментарий». С #if DEAD- это канонический и лучший пример. Во многих языках вы можете просто обернуть мертвый код в эквивалент if (DEAD). А во многих IDE вы можете фактически удалить мертвый код и использовать Ctrl + Z и / или контроль версий, чтобы вернуть его, если хотите. Оставляя комментарий, любая строка документа, чей текст представляет собой кучу мертвого кода, по-прежнему является худшим вариантом для удобства чтения.
Quuxplusone
11

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

SK-логика
источник
3
Я бы не согласился с «большинством» в наше время. Конечно, это традиционный способ, но я знаю, что для C EDG объединяет препроцессор, лексинг и синтаксический анализ, и я подозреваю, что и GCC, и Microsoft тоже. Преимущество состоит в том, что он позволяет вам реализовать их отдельно, если вам нужно.
Эндрю Айлетт
Clang тоже делает то же самое. Но это все еще лишь небольшая часть существующих популярных компиляторов языков.
SK-logic
@Neil Butterworth, взгляните на mcs, javac, gcc (да, он исправляет лексер, но все же это выделенный проход лексинга), clang (так же, как gcc), dmd, fpc и многие, многие другие.
SK-logic
Никто не использует регулярные выражения в своих лексингах для любого нетривиального компилятора.
Нуоджи
@Nuoji - для нетривиальных - конечно. Но те, кто полагаются на гибкие и подобные инструменты, делают.
SK-logic
7

Вполне возможно создать лексер, который может обрабатывать вложенные комментарии. Когда он ест пустое пространство, когда он видит, /*он может увеличивать счетчик глубины, уменьшать его, когда видит */, и останавливаться, когда глубина равна нулю. Тем не менее, я сделал много парсеров, и никогда не находил веских причин для комментариев вложения.

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

Недостаток комментариев, которые не вкладываются, выглядит примерно так:

/*
some code
more code
blah blah blah
/**/

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

Майк Данлавей
источник
1
//комментарии также в стиле C99.
JAB
В качестве альтернативы язык может указывать начало комментария /*$token, где identifierнаходится любой буквенно-цифровой токен, и конец комментария token$*/. Для токенизатора было бы относительно просто включить код для проверки того, что каждая метка конечного комментария содержит соответствующий токен для соответствующего блока начального комментария.
суперкат
5

Поскольку никто другой не упомянул об этом, я перечислю несколько языков, которые поддерживают вложенные комментарии: Rexx, Modula-2, Modula-3, Oberon. Несмотря на все жалобы по поводу сложности и скорости, ни у одного из них нет серьезных проблем.

Rugxulo
источник
4
К которому я добавляю: Хаскелл, Фреге
Инго
Также поддерживается Scala.
Мэтт R
4

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

Альтернативный метод состоит в том, чтобы добавить строку строки с начальной последовательностью комментария строки, если у вас есть редактор, который поддерживает это.

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

Инго
источник
3

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

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

AlexRS
источник
1
+1 за «проще добавить функцию, чем удалить ее».
R ..
3
как только вы запретите вложенные комментарии, вы также не сможете их разрешить, потому что это нарушит такие комментарии:/*/**/
RiaD
2

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

Хаммар
источник
3
Это не "аромат". Слово «регулярный» в регулярном выражении по своей сути исключает рекурсию.
R ..
3
@R: В математике, конечно. Но в программировании у нас есть вещи, которые мы называем регулярными выражениями, которые поддерживают рекурсию.
Амара
Вопрос: это вообще проблема? Большинство языков уже имеют дело с вложенными скобками. Чтобы назвать некоторые: Lisp, C, Java, Python, Ruby, Perl.
Томас Эдинг
Вложенные скобки хороши, потому что вещи внутри скобок такие же, как и вещи снаружи: нормальные токены. В комментариях у вас нет токенов, у вас просто есть текст. Вы должны иметь возможность сопоставлять начальный и конечный токены комментариев, чтобы вы знали, является ли int типом или просто словом в комментарии. (Особенно, если вы исключите комментарии в лексере.)
Алан Шутко
2
@ThePopMachine: Я уверен в том, что я сказал, что регулярное имеет определенное формальное значение, а не значение, которое вы используете, и что «регулярное» в «регулярном выражении» было выбрано для этого значения. Быть нерекурсивным является одним из результатов его определения.
R ..
-1

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

Нил Баттерворт
источник
-1

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

Гас
источник
3
-1: не правда. Нормальные парсеры так не работают.
Амара