Почему числовые имена функций не допускаются?

10

Учтите следующее:

$ ksh -c '1(){ echo hi;};1'
ksh: 1: invalid function name
$ dash -c '1(){ echo hi;};1'
dash: 1: Syntax error: Bad function name
$ bash -c '1(){ echo hi;};1'
bash: `1': not a valid identifier
bash: 1: command not found
$ mksh -c '1(){ echo hi;};1'
hi

По сути, я пытался объявить функции, 1и 0это было бы сокращением для trueи false, но, как вы можете видеть, я столкнулся с проблемой использования числовых имен в функциях. Такое же поведение происходит с псевдонимами и двузначными именами.

Вопрос "почему"? Это предписано POSIX? или просто причудливые раковины?

Смотрите также связанный с этим вопрос .

Сергей Колодяжный
источник
1
Вещи, которые предписаны posix, в большинстве случаев являются причудливыми оболочками, похожими на Bourne. : P
Муру
Я вижу что ты тут делал . , , > :) lol
Сергей Колодяжный
4
@fkraiem Пожалуйста, обратитесь к meta.askubuntu.com/q/13807/295286 Сценарии оболочек / оболочек есть и всегда были в теме Ask Ubuntu :) Это важная тема для правильного системного администрирования любой системы Ubuntu
Сергей Колодяжный,
4
Стоит отметить, что он 0находится trueв сценариях оболочки и 1является false(на самом деле, любой ненулевой объект рассматривается как ложный), в случае, если кто-либо, читающий это, не знает. Это назад от большинства других языков программирования.
Итан Камински
2
@EthanKaminski Да, что касается состояния выхода команд , это абсолютно верно. Возвращаемое значение 0 находится trueв оболочке. Тем не менее, в арифметическом расширении $((...))возвращаются состояния возврата - 1 означает, trueа 0 falseсоответствует согласованности с синтаксисом языка Си. Попробуйте, например, bash -c 'echo $((1==1));echo $((1==2))' То, что я пытался сделать вне этого вопроса, на самом деле было «обратным» поведением. Посмотрите последний пример моего ответа здесь, чтобы увидеть, что именно я пытался сделать. Глупая идея, но тем не менее работает
Сергей Колодяжный

Ответы:

14

POSIX говорит:

2.9.5 Команда определения функции

Функция - это пользовательское имя, которое используется как простая команда для вызова составной команды с новыми позиционными параметрами. Функция определяется с помощью «команды определения функции».

Формат команды определения функции следующий:

 fname ( ) compound-command [io-redirect ...]

Функция называется fname ; приложение должно убедиться, что это имя (см. Имя XBD ) и что это не имя специальной встроенной утилиты. Реализация может разрешить другие символы в имени функции в качестве расширения. Реализация должна поддерживать отдельные пространства имен для функций и переменных.

И:

3.235 Имя

В языке команд оболочки слово, состоящее исключительно из символов подчеркивания, цифр и алфавита из переносимого набора символов. Первый символ имени не является цифрой.

Примечание. Портативный набор символов подробно описан в разделе «Портативный набор символов».

Таким образом, слово, начинающееся с цифры, не может быть именем функции.

Мур
источник
Тем не менее, POSIX не совсем объясняет почему, но я восприму это как ответ «Потому что стандарты». Спасибо
Сергей Колодяжный
4
@SergiyKolodyazhnyy Я бы сказал, что это наследственная вещь. Этот стандарт для имен довольно распространен и в других вещах (имена IIRC C также следуют тому же стандарту), так что, вероятно, это вещь Unix. Кроме того, в C, это облегчает разбор
muru
3
@muru в C это принесло бы некоторую двусмысленность, если бы это было позволено. Например, что бы это 1Lзначило? Имя функции? Или long intбуквальный?
Руслан
2
Помимо вышесказанного, стоит отметить, что в C голое имя функции может выступать в качестве указателя на эту функцию. Это позволяет передавать функции в качестве параметров функции, сохранять ссылки на них в переменных и т. Д. Часто используется для обратных вызовов. Это в отличие от имени функции, за которым следует (), возможно, с аргументами внутри, которое обозначает вызов рассматриваемой функции (и принимает значение, которое возвращается вызываемой функцией). Так что, если у вас есть функция int f() { return 42; }на C, fона действительна в контексте указателя и f()действительна в целочисленном контексте без указателя.
CVn
13

Это стандарт во многих языках для предотвращения путаницы между математическими операциями и переменными или функциями или методами.

Рассматривать:

var 1 = 100

print 1*10 //should return 10 but would instead return 1000

var x = 5
x += 1
print x //returns 105, not 6    

def 100(num)
  return num * 1000
end

var y = 10 + 100(10)
print y // returns 100010 instead of 1010

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

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

мистифицировать
источник
Я собирался прокомментировать «но переменные в оболочке должны быть добавлены $перед расширением», но опять же, если оболочка вдохновлена ​​другими языками, это нормально, я полагаю, плюс в арифметических расширениях ((переменные не обязательно должны иметь ведущие $. Хорошо, я могу понять это
Сергей Колодяжный
3
Да, это соглашение, потому что оно будет создавать неожиданные результаты почти на каждом языке, но даже в ситуации, когда это будет работать, это может очень затруднить понимание кода для тех, кому придется работать над вашим кодом после вас.
Джош
2
@SergiyKolodyazhnyy арифметическое расширение позволяет ссылаться на имена переменных без $, так что вот так. Но это, вероятно, вторично к другой причине «просто следовать общему соглашению»
Хоббс
@hobbs Да, абсолютно с этим согласен
Сергей Колодяжный
1
Это объяснение "большинства языков" не имеет большого смысла для оболочек. Все оболочки Bourne стиля имеют параметры, имена которых похожи на числовые литералы или оператор: 0для имени оболочки или сценария 1, 2..., для позиционных параметров, *для них присоединились, -для опции включено, ?для последнего состояния выхода, и !для PID самого последнего асинхронного задания. (Таким образом, даже в $(( )), $это часто необходимо.) Код, показанный здесь, чтобы продемонстрировать предлагаемое обоснование, не является сценарием для любой оболочки в стиле Борна, так как нет способа продемонстрировать это таким образом, так как он не применяется к их.
Элия ​​Каган
10

В C рассмотрим выражение вроде:

1000l + 2.0f;

Является ли 1000lпеременная или константа? Поскольку имена переменных не могут начинаться с цифры, это должна быть константа. Это делает анализ более простым и строгим (опечатки, такие как 1000kлегко могут быть пойманы). Также проще иметь одно правило для переменных и имен функций, поскольку функции также могут рассматриваться как переменные. Теперь, конечно, парсеры намного сложнее и мощнее, и у нас есть такие вещи, как пользовательские литералы в C ++. Но назад, в те древние времена доисторического периода, пожертвование небольшим количеством ненужной гибкости может значительно сократить время вашей компиляции (или интерпретации) (и люди по-прежнему жалуются на время компиляции C ++).

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

OLORIN
источник
2
Поскольку объяснения идут, это правильное. Дело не в том, что одни и те же соображения применимы ко всем языкам или что у оболочек стиля Борна синтаксис похож на синтаксис C, но культура, связанная с C, была сильной, и разработчики оболочки должны были придумать некоторые гарантии относительно того, какие идентификаторы будут разрешается. Я думаю, что здесь можно использовать примеры «вы можете увидеть влияние влияния C на язык оболочки», поскольку сходства между ними действительно не перевешивают различия (например, подумайте, какие числа считаются истинными ). Тем не менее, этот ответ правильный.
Элия ​​Каган
@Eliah, возможно, вещь чисел также является прямым следствием состояний выхода для успеха и неудачи в C, поэтому я склонен мыслить с точки зрения успеха и неудачи вместо true и false при написании тестов оболочки. Вы правы в том , что много оболочки синтаксиса не что иное , как C, но примеры включают фигурные скобки, с запятой, короткое замыкание &&и ||отсутствие поддержки для ASCII NUL в строках,
OLORIN