Некоторое время назад я работал с новым разработчиком C++, когда он задал вопрос: «Почему имена переменных не могут начинаться с цифр?»
Я не мог придумать ответа, за исключением того, что в некоторых числах может быть текст (123456L, 123456U), и это было бы невозможно, если бы компиляторы думали, что все с некоторым количеством альфа-символов было именем переменной.
Это был правильный ответ? Есть еще причины?
string 2BeOrNot2Be = "that is the question"; // Why won't this compile?
Повторно пометил это с помощью «C++», потому что это языковое ограничение. Вполне возможно, что некоторые языки позволят это (хотя я не могу придумать ничего навскидку).
Эта проблема появилась раньше C++, по крайней мере, на 20 лет, если не до первых макроассемблеров.
OP конкретно упомянул C++, но мне все равно больше нравится новый набор тегов.
Что ж, в FORTH вы можете это сделать. AFAIK, есть слово 0, которое помещает 0 в стек. другой - 0=, который проверяет, находится ли 0 в стеке.
Почему этот вопрос так популярен, а ответы на него так неправильны? Во многих языках переменные могут начинаться с цифр. В C++ нет, но это просто удобное ограничение, позволяющее избежать некоторых двусмысленностей. Иногда ТАК меня поражает совершенно неправильным образом.
Если этот вопрос был задан сегодня на SO, он будет называться основанным на мнении и закрытым. Спасибо, что спросили об этом.
@ david.pfx Лично я ожидаю, что почти в каждом отдельном языковом ограничении где-то задают вопрос «почему». ИМО, это хорошо, это означает, что программисты думают о том, что они делают, и хотят учиться.
@Boon Ну ... я все еще открыт. ИМО, причина закрытия POB была бы неверной, потому что кому-то в какой-то момент нужно было реализовать это ограничение, и для этого была причина (даже если это было просто «Я ненавижу цифры» или «Я хотел уйти рано в пятницу. "), чтобы ответ одного человека был абсолютной правдой. Гипотетически, если бы этот человек задал этот вопрос или кто-то случайно прочитал его книгу / статью / блог / статью в журнале, был бы найден истинный ответ.
Также связанный разместить на SE.SE
@jrh: Нет, вопрос в порядке, и на него может быть хороший ответ (который я мог бы даже написать, но не буду). Удивительно, сколько существует ответов и насколько большинство из них неверны (включая принятый ответ).
@OutlawProgrammer - один из примеров - пакетный: это %valid variable name%. %2 Be Or Not 2 Be % также действителен. Все пробелы значимы
@ChristianFritz, почему вы удаляете тег C++? Это не зависит от языка, поскольку многие языки позволяют переменным начинаться с числа, например сценарии оболочки $1.
@Tim не в C++, но многие другие языки позволяют, чтобы Почему в именах переменных не может быть пробелов?, Есть ли какой-либо язык, который позволяет использовать пробелы в именах переменных, Почему идентификаторы не должны начинаться с числа?
Технически это возможно на любом языке, но делает лексический анализ более сложным. См. en.wikipedia.org/wiki/Lexical_analysis





Хорошо подумайте об этом:
int 2d = 42;
double a = 2d;
Что такое? 2.0? или 42?
Подсказка: если вы не поняли, d после числа означает, что число перед ним является двойным литералом
На самом деле это [относительно] позднее появившаяся нотация ("d" для "двойного") стандарта C89 IIRC. Ведущие числа в идентификаторах невозможны, если эта конструкция написана на языке, но это не причина, по которой числа не могут начинать идентификатор.
d не является допустимым суффиксом плавающего литерала в C++. Плавающие литералы по умолчанию являются двойными, вы можете использовать f или l, если вам нужен плавающий или длинный двойной литерал.
Это для Java, и хотя исходный вопрос был для C++, он также применим ко многим другим языкам, таким как Java. Но я согласен. Это не основная причина, по которой идентификаторы не могут начинаться с цифр.
Потому что тогда строка цифр будет как действительным идентификатором, так и действительным числом.
int 17 = 497;
int 42 = 6 * 9;
String 1111 = "Totally text";
Что, если они сказали, что переменные не могут быть только числами. И что?
Мне потребовалось бы больше времени, чтобы придумать регулярное выражение для лексера, которое могло бы подбирать идентификаторы с использованием этого правила, если это вообще возможно, поэтому я могу понять, почему ни один язык никогда не был реализован таким образом, в дополнение к причинам, указанным в другие ответы.
вы можете сделать правила сколь угодно сложными, но вы можете пожалеть об этом, когда попытаетесь реализовать компилятор. ;-)
примечание - я не защищаю это - просто говорю, что эта причина находится далеко внизу в списке, и, скорее всего, все это просто из-за условностей.
Мне особенно нравится возможность изменять числа - «int 1 = 2; int a = 1 + 1;» установил бы на 4. :-)
Если люди собираются вести себя глупо, то «L» выглядит как «1» - как в l234 (это L234) - похоже на число, но допустимо. Если вы хотите написать тупой код вроде «17 = 497», тогда использование «L» сделает это возможным. Но почему? -Р
Этот ответ на самом деле находится на правильном пути. Настоящая проблема заключается в производительности. Отслеживание с возвратом может сделать правильные регулярные выражения очень медленными.
Если бы это были числа + альфа, вы все равно могли бы сделать String 0x123 = "Hello World". Если вы не укажете, что имена переменных - это «числа + альфа, которые не соответствуют допустимому числовому обозначению», и это просто глупо.
Некоторые языки делать поддерживают назначение поверх чисел. Эти языки позволят использовать такой код, как присвоение 3 равным 4.
Не обращайте внимания на компилятор: людям используя язык нужно уметь легко (с первого взгляда) отличать имена переменных от чисел. Если бы первый символ не сказал вам - вместо этого, если бы вам нужно было перебрать остальную часть слова, чтобы определить, есть ли где-то нечисловая буква - код будет труднее читать.
@eaolson: Я работал с ассемблером, который применил это правило к шестнадцатеричным числам, которые начинались с A-F и заканчивались h. Меня сбило с толку, когда я в первый раз попытался определить ярлык, указывающий на музыкальные данные для Двухголосного изобретения № 13 Баха (логическое имя? Bach).
Это не правильно. Вопрос касался переменных, начинающихся с цифр, а не полностью состоящих из чисел.
«Если вы не укажете, что имена переменных - это« числа + альфа, которые не преобразуются в допустимое числовое обозначение », и это просто глупо». Но языки делают именно это для ключевых слов: имя переменной - это последовательность букв, которая не преобразуется в допустимое зарезервированное слово.
@municious Верно, но список зарезервированных слов конечен, тогда как список допустимых числовых указателей бесконечен или почти бесконечен.
Это принятый ответ, и он совершенно неверен. Я пишу компиляторы, и очень легко позволить идентификатору быть строкой символов, содержащей хотя бы одну букву, независимо от того, с чего он начинается.
Компиляторы / парсеры / лексические анализаторы были для меня давным-давно, но я думаю, что помню, как было трудно однозначно определить, представляет ли числовой символ в модуле компиляции литерал или идентификатор.
Языки, в которых пробел не важен (например, ALGOL и оригинальный FORTRAN, если я правильно помню), по этой причине не могли принимать числа для начала идентификаторов.
Это восходит к прошлому - до специальных обозначений для обозначения памяти или числовой базы.
Вероятно, это решение было принято по нескольким причинам: когда вы разбираете токен, вам нужно только посмотреть на первый символ, чтобы определить, является ли он идентификатором или литералом, а затем отправить его в нужную функцию для обработки. Так что это оптимизация производительности.
Другой вариант - проверить, не является ли это литералом, и оставить доменом идентификаторов вселенную без литералов. Но для этого вам нужно будет изучить каждый символ каждого токена, чтобы знать, как его классифицировать.
Существует также стилистический подтекст: идентификаторы должны быть мнемоникой, поэтому слова запоминать намного легче, чем числа. Когда писалось множество оригинальных языков, задающих стили на следующие несколько десятилетий, они не думали о замене «2» на «to».
Я думаю, что простой ответ - может, ограничение основано на языке. В C++ и многих других это невозможно, потому что язык не поддерживает это. Это не разрешено правилами.
Этот вопрос похож на вопрос, почему король не может перемещать четыре клетки за раз в шахматах? Это потому, что в шахматах это недопустимый ход. Может это в другой игре точно. Это просто зависит от правил игры.
За исключением того, что C++ недавно изобрели люди, которые еще живы. Мы можем спросить их, почему они выбрали то, что сделали, и отвергли альтернативы. То же самое не относится к шахматам.
Но я не об этом говорю. Это аналогия того, почему в начале имен переменных не может быть чисел, и самый простой ответ - потому что правила языка этого не допускают.
Конечно, но я не думаю, что спрашивающий - идиот. Он, наверное, так далеко уже разобрался сам. Вопрос ИМО: «Почему правила языка не позволяют этого?». Он хочет преодолеть разрыв между знанием правил и их пониманием.
Да, поразмыслив над этим, я понял, куда ты идешь. У вас есть точка. Я предполагаю, что я применял бритву Оккама немного вольно и предполагал, что нет реального ответа на вопрос, почему, кроме того, что переменные не начинаются с чисел, потому что нет чисел.
Я не говорю, что вы ошибаетесь, заметьте, иногда решения органов по стандартизации C++ действительно превосходят понимание смертных, и в итоге вы получаете «потому что они должны были что-то решить, и они решили это». Но есть, по крайней мере, вопрос :-)
Использование цифры в начале имени переменной значительно усложняет проверку ошибок во время компиляции или интерпретации.
Разрешение использования имен переменных, начинающихся с числа, вероятно, вызовет огромные проблемы для разработчиков языка. Во время синтаксического анализа исходного кода, всякий раз, когда компилятор / интерпретатор обнаруживал токен, начинающийся с цифры, где ожидалось имя переменной, ему приходилось искать по огромному сложному набору правил, чтобы определить, действительно ли токен является переменной или ошибкой. . Дополнительная сложность, добавленная к синтаксическому анализатору языка, может не оправдать эту функцию.
Насколько я себя помню (около 40 лет), я не думаю, что когда-либо использовал язык, который позволял бы использовать цифру в начале имен переменных. Я уверен, что это было сделано хоть раз. Может быть, кто-то здесь действительно где-то видел это.
Это не так уж и сложно. Это усложняет лексическую фазу, вот и все. Конечно, когда я брал компиляторы, мне говорили, что лексическое сканирование может занимать более четверти общего времени компиляции.
Как заметили несколько человек, существует много исторического багажа о допустимых форматах для имен переменных. А языковые дизайнеры всегда зависят от того, что они знают, когда создают новые языки.
Тем не менее, почти всегда язык не позволяет именам переменных начинаться с цифр, потому что это правила дизайна языка. Часто это происходит потому, что такое простое правило значительно упрощает синтаксический анализ и лексирование языка. Однако не все разработчики языков знают, что это настоящая причина. Современные инструменты лексирования помогают, потому что, если вы попытаетесь определить его как допустимое, они вызовут конфликты при синтаксическом анализе.
OTOH, если в вашем языке есть однозначно идентифицируемый символ для обозначения имен переменных, можно настроить их так, чтобы они начинались с числа. Подобные варианты правил также могут использоваться для разрешения пробелов в именах переменных. Но полученный в результате язык, скорее всего, не будет сильно напоминать какой-либо популярный традиционный язык, если вообще будет.
В качестве примера довольно простого языка шаблонов HTML, который позволяет переменным начинаться с цифр и иметь встроенные пробелы, посмотрите Qompose.
На самом деле существует несколько языков, которые позволяют использовать символы для обозначения идентификаторов. Их называют «сигилами», и они есть в Perl и PHP.
За исключением того, что вам по-прежнему не разрешается начинать имя переменной в PHP с числа - это запрещено правилами языка. :-) Но в Qompose можно по той же причине.
C++ не может иметь этого, потому что разработчики языка сделали это правилом. Если бы вы создали свой собственный язык, вы, конечно, могли бы это разрешить, но вы, вероятно, столкнетесь с теми же проблемами, что и они, и решите не позволять этого. Примеры имен переменных, которые могут вызвать проблемы:
0x, 2d, 5555
Это ограничение действует в языках, где такой синтаксис не разрешен.
Вероятно, потому, что так человеку легче определить, число это или идентификатор, а также в силу традиции. Наличие идентификаторов, которые могут начинаться с цифры, не сильно усложнит лексическое сканирование.
Не во всех языках есть запрещенные идентификаторы, начинающиеся с цифры. В Forth они могли быть числами, а маленькие целые числа обычно определялись как слова Forth (по сути, идентификаторы), поскольку было быстрее читать «2» как процедуру для помещения 2 в стек, чем распознавать «2» как число. чье значение было 2. (При обработке ввода от программатора или блока диска система Forth разделяла ввод по пробелам. Она пыталась найти токен в словаре, чтобы увидеть, было ли это определенное слово, и в противном случае попытался бы преобразовать его в число, а в противном случае - пометил бы ошибку.)
Дело в том, что у Forth действительно нет очень сложного парсера. На самом деле все, что его волнует, - это то, находится ли идентификатор между двумя наборами пробелов.
Предположим, вы разрешили имена символов начинаться с цифр. Теперь предположим, что вы хотите назвать переменную 12345foobar. Как бы вы отличили это от 12345? На самом деле это не так уж сложно сделать с регулярным выражением. Проблема на самом деле заключается в производительности. Я не могу объяснить, почему это так подробно, но, по сути, все сводится к тому факту, что для отличия 12345foobar от 12345 требуется возврат. Это делает регулярное выражение недетерминированным.
Есть гораздо лучшее объяснение этому здесь.
Как разработать регулярное выражение, позволяющее использовать переменную с именем ifq или doublez, но не if или double? Основная проблема с разрешением идентификаторам начинаться с цифр заключается в том, что существуют существующие формы шестнадцатеричных литералов и чисел с плавающей запятой, которые полностью состоят из буквенно-цифровых символов (языки будут использовать что-то вроде $ 1234 или h'1234 вместо 0x1234 и требовать такие числа, как 1E23, чтобы включить точку, можно было бы избежать этой проблемы). Обратите внимание, что попытки синтаксического анализа регулярных выражений C уже могут быть сорваны такими вещами, как 0x12E+5.
Я согласен, что было бы удобно разрешить идентификаторам начинаться с цифры. Один или два человека упомянули, что вы можете обойти это ограничение, добавив знак подчеркивания к своему идентификатору, но это действительно некрасиво.
Я думаю, что отчасти проблема связана с числовыми литералами, такими как 0xdeadbeef, которые затрудняют создание легко запоминающихся правил для идентификаторов, которые могут начинаться с цифры. Один из способов сделать это - разрешить все, что соответствует [A-Za-z _] +, но НЕ является ключевым словом или числовым литералом. Проблема в том, что это приведет к тому, что будут разрешены такие странные вещи, как 0xdeadpork, но не 0xdeadbeef. В конце концов, я считаю, что мы должны быть справедливыми по отношению ко всему мясу: P.
Помню, когда я впервые изучал C, я чувствовал, что правила для имен переменных были произвольными и ограничительными. Хуже всего то, что их было трудно запомнить, поэтому я отказался от попыток их выучить. Я просто делал то, что считал правильным, и это сработало очень хорошо. Теперь, когда я узнал намного больше, это не кажется таким уж плохим, и я наконец нашел время, чтобы выучить это правильно.
LOL - «Проблема в том, что это приведет к тому, что будут разрешены такие странные вещи, как 0xdeadpork, но не 0xdeadbeef. В конечном счете, я думаю, что мы должны быть справедливыми по отношению ко всему мясу: P».
Одна из ключевых проблем ослабления синтаксических соглашений заключается в том, что они вносят когнитивный диссонанс в процесс кодирования. На то, как вы думаете о своем коде, может сильно повлиять отсутствие ясности, которое он привнесет.
Разве не Дайкстра сказал, что «самый важный аспект любого инструмента - это его влияние на пользователя»?
Потому что, если вы разрешили ключевому слову и идентификатору начинаться с числовых символов, лексер (часть компилятора) не мог легко отличить начало числового литерала от ключевого слова, не становясь намного сложнее (и медленнее).
Процесс лексирования редко бывает узким местом. Конечно, это усложняет регулярное выражение для токенов идентификаторов, но они все равно могут быть сверхбыстрыми DFA. По сравнению с большинством других задач, которые приходится выполнять компиляторам, время их выполнения - мелочь.
Сейчас это конвенция, но начиналась она как техническое требование.
Раньше синтаксические анализаторы языков, таких как FORTRAN или BASIC, не требовали использования пробелов. Итак, в основном следующие идентичны:
10 V1=100
20 PRINT V1
и
10V1=100
20PRINTV1
Теперь предположим, что числовые префиксы разрешены. Как бы вы это интерпретировали?
101V=100
как
10 1V = 100
или как
101 V = 100
или как
1 01V = 100
Итак, это было объявлено незаконным.
Незначительный нюанс: номера строк должны быть в столбцах 1-6, а исполняемый код после столбца 8. С другой стороны, DO 10 I=1,50 может быть неоднозначно проанализирован как DO1 0I=1,50 [кстати, если использовать точку вместо запятой, оператор становится присваиванием в переменную с плавающей запятой с именем DO10I.
Интересное объяснение! Это имеет смысл для старых языков, но все еще заставляет меня задаться вопросом, почему мы все еще продолжаем выбирать дизайн для таких языков, как Python, JavaScript или R.
Я определенно помню это с BASIC и считаю, что это, вероятно, самая веская практическая причина практики. Технически, однако, я смутно помню, что на самом деле он может вернуться к раннему ассемблеру. Я не уверен, что такое ассемблер, и вполне могу ошибаться.
Ограничение произвольное. В различных Лиспах имена символов могут начинаться с цифр.
Первоначально это было просто потому, что легче запомнить (вы можете придать ему больше смысла) имена переменных как строки, а не числа, хотя числа могут быть включены в строку, чтобы улучшить значение строки или разрешить использование того же имени переменной, но обозначить его как имеющее отдельный, но близкий смысл или контекст. Например, loop1, loop2 и т. д. Всегда будут сообщать вам, что вы находитесь в цикле и / или цикл 2 был циклом внутри цикла loop1. Что бы вы предпочли (имеет большее значение) в качестве переменной: адрес или 1121298? Что легче запомнить? Однако, если в языке используется что-то для обозначения того, что это не просто текст или числа (например, $ в адресе $), это действительно не должно иметь значения, поскольку это сообщит компилятору, что то, что следует далее, следует рассматривать как переменную ( в таком случае). В любом случае все сводится к тому, что разработчики языка хотят использовать в качестве правил для своего языка.
Имена переменных не могут начинаться с цифры, потому что это может вызвать некоторые проблемы, как показано ниже:
int a = 2;
int 2 = 5;
int c = 2 * a;
каково значение c? равно 4 или 10!
другой пример:
float 5 = 25;
float b = 5.5;
это первая цифра 5 или объект (оператор.) Аналогичная проблема со вторым 5.
Может быть, есть еще какие-то причины. Итак, мы не должны использовать какие-либо цифры в начале имени переменной.
Даже если требуется, чтобы идентификаторы содержали хотя бы один нецифровой символ, нужно было бы также потребовать, чтобы числовые форматы, содержащие буквы, также содержали не буквенно-цифровой символ [например, требуется, чтобы 0x1234 записывалось как $ 1234 и 1E6 было записано как 1.E6 или 1.0E6] или же иметь странную комбинацию допустимых и недопустимых имен идентификаторов.
компилятору легко идентифицировать переменную, используя ASCII в ячейке памяти, а не по номеру.
Потому что при лексическом анализе во время компиляции исключается возврат с возвратом. Такая переменная, как:
Apple;
компилятор сразу узнает, что это идентификатор, когда он встретит букву «А».
Однако такая переменная, как:
123apple;
компилятор не сможет решить, является ли это числом или идентификатором, пока он не достигнет «a», и в результате ему потребуется возврат с возвратом.
Чтобы ответить, вспомнив мой класс проектирования компилятора, этот ответ идет прямо! Престижность
COBOL позволяет переменным начинаться с цифры.
Переменная может рассматриваться как значение также во время компиляции компилятором. поэтому значение может вызывать значение снова и снова рекурсивно
На этапе лексического анализа при компиляции фрагмента кода исключается возврат с возвратом.. Переменная вроде Apple; , компилятор сразу узнает свой идентификатор, когда встретит букву «A» на этапе лексического анализа. Однако такая переменная, как 123apple; , компилятор не сможет решить, является ли это числом или идентификатором, пока он не достигнет «a» и ему не потребуется выполнить обратный поиск, чтобы перейти на фазу лексического анализа, чтобы определить, что это переменная. Но в компиляторе это не поддерживается.
Компилятор имеет следующие 7 этапов:
На этапе лексического анализа при компиляции фрагмента кода исключается обратный поиск. Такая переменная, как Apple, компилятор узнает ее идентификатор сразу же, когда он встретит букву «A» на этапе лексического анализа. Однако для такой переменной, как 123apple, компилятор не сможет решить, является ли это числом или идентификатором, пока он не достигнет «a», и ему потребуется возврат с возвратом, чтобы перейти на фазу лексического анализа, чтобы определить, что это переменная. Но в компиляторе это не поддерживается.
Когда вы анализируете токен, вам нужно только посмотреть на первый символ, чтобы определить, является ли он идентификатором или литералом, а затем отправить его в нужную функцию для обработки. Итак, это оптимизация производительности.
Когда дело доходит до объявления переменной, в этом не может быть ничего плохого, но есть некоторая двусмысленность, когда он пытается использовать эту переменную где-то еще, например:
let 1 = "Привет, мир!" печать (1) печать (1)
print - это общий метод, который принимает все типы переменных. поэтому в этой ситуации компилятор не знает, к какому (1) программисту относится: к 1 целочисленного значения или 1, хранящему строковое значение. может быть, лучше для компилятора в этой ситуации позволить определить что-то подобное, но при попытке использовать этот неоднозначный материал выведите ошибку с возможностью исправления, чтобы исправить эту ошибку и устранить эту неоднозначность.
И почему в них не может быть пробелов?