Чому імена числових функцій не дозволені?


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
Речі, покладені на позицію, - це здебільшого колись примхи раковин Борна. : P
муру

Я бачу, що ви там робили . . . > :) lol
Сергій Колодяжний

4
@fkraiem Будь ласка, зверніться до meta.askubuntu.com/q/13807/295286 Оболонки / сценарії оболонок є і завжди були на тему "Попросити 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 останньої асинхронної роботи. (Таким чином, навіть в $(( )), то $часто потрібно.) Код , показаний тут , щоб продемонструвати запропоноване пояснення не сценарій для будь-якої оболонки Bourne стилю, так як немає ніякого способу , щоб продемонструвати, що шлях, так як це не відноситься до їх.
Елія Каган

10

В C розглянемо такий вираз:

1000l + 2.0f;

Є чи 1000lзмінна або константа? Оскільки назви змінних не можуть починатися з цифри, це повинно бути константою. Це робить розбір простішим і суворішим (помилки на кшталт цього 1000kможуть бути легко зафіксовані). Також простіше мати єдине правило для змінних і імен функцій, оскільки функції можуть також розглядатися як змінні. Тепер звичайно, парсери набагато складніші та потужніші, і у нас є такі речі, як нестандартні літерали в C ++. Але ще в ті давні часи передісторії, жертвуючи трохи непотрібної гнучкості, може зробити ваші компіляції (або інтерпретацію) рази набагато коротшими (а люди все ще скаржаться на час збирання C ++).

І ви можете побачити ефекти впливу С у всій мові оболонки, тому не дивно, що оболонка Борна (або оболонка С) і, отже, POSIX, обмежили клас дозволених імен таким же, як у C.


2
По мірі пояснень це правильне. Справа не в тому, що однакові міркування стосуються всіх мов або що оболонки у стилі Борна мають синтаксис, подібний до C, але що культура, пов'язана з C, була сильною, і дизайнери оболонок повинні були скласти певні гарантії щодо того, які саме ідентифікатори будуть дозволено. Я думаю, що для цього можна використати приклади "ви можете побачити наслідки впливу С на всій мові оболонки", оскільки подібності між ними справді не переважують відмінностей (подумайте, наприклад, які числа вважаються істинними , наприклад). Тим не менш, ця відповідь правильна.
Елія Каган

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