为什么不允许使用数字函数名称?

Ser*_*nyy 10 command-line bash dash-shell ksh

考虑以下:

$ 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
Run Code Online (Sandbox Code Playgroud)

基本上,我试图声明函数10这将是trueand 的简写false,但是正如您所看到的,我在函数中使用数字名称时遇到了问题。别名和两位数名称也会发生相同的行为。

问题是“为什么”?它是 POSIX 强制要求的吗?或者只是像伯恩一样的贝壳的怪癖?

另请参阅相关的问题

mur*_*uru 14

POSIX 说:

2.9.5 功能定义命令

函数是用户定义的名称,用作调用具有新位置参数的复合命令的简单命令。函数是用“函数定义命令”定义的。

函数定义命令的格式如下:

 fname ( ) compound-command [io-redirect ...]
Run Code Online (Sandbox Code Playgroud)

该函数名为fname;应用程序应确保它是一个名称(请参阅 XBD名称)并且它不是特殊内置实用程序的名称。实现可能允许函数名称中的其他字符作为扩展名。实现应为函数和变量维护单独的名称空间。

和:

3.235 姓名

在 shell 命令语言中,一个仅由可移植字符集中的下划线、数字和字母组成的单词。名称的第一个字符不是数字。

注意:可移植字符集在可移植字符集中有详细定义。

所以以数字开头的单词不能是函数名。

  • @SergiyKolodyazhnyy 我会说这是一种遗传的东西。这个名称标准在其他方面也很常见(IIRC C 名称也遵循相同的标准),所以它可能是 Unix 的东西。此外,在 C 中,它更容易解析 (4认同)
  • @muru 在 C 中,如果允许的话,它会带来一些歧义。例如,“1L”是什么意思?函数名?还是“long int”字面量? (3认同)
  • 除此之外,值得注意的是,在 C 中,一个裸函数名可以充当指向该函数的指针。这允许您将函数作为参数传递给函数,在变量中存储对它们的引用等。通常用于回调。这与后跟`()`的函数名称形成对比,其中可能带有参数,表示对相关函数的调用(并采用被调用函数返回的值)。所以如果你有一个函数 `int f() { return 42; }` 在 C 中,`f` 在指针上下文中有效,而 `f()` 在非指针整数上下文中有效。 (2认同)

Jos*_*osh 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
Run Code Online (Sandbox Code Playgroud)

如您所见,如果允许数字作为变量或函数名称,那么稍后在程序中进行数学运算可能会变得非常混乱,如果您稍后需要实际使用这些数字进行数学运算,则必须想出创造性的解决方法。它还可以在某些语言中产生意想不到的结果。想象一下,您正在为循环增加一个数字,但其中一个数字已经是一个等于字符串的变量。它会立即抛出错误。如果您不是代码的原始作者,则可能需要很长时间才能找到该错误。

简而言之,这就是为什么大多数语言不允许您使用数字作为变量、函数或方法等的名称。

  • 是的,这是一个约定,因为它几乎在所有语言中都会产生意想不到的结果,但是,即使在它可以工作的情况下,它也会使代码很难被那些必须在您之后处理您的代码的人理解。 (3认同)
  • @SergiyKolodyazhnyy 算术扩展允许在没有`$` 的情况下引用变量名,所以就是这样。但这可能是“只是遵循共同约定”的另一个原因的次要原因 (2认同)

Olo*_*rin 10

在 C 中,考虑如下表达式:

1000l + 2.0f;
Run Code Online (Sandbox Code Playgroud)

1000l变量还是常数?因为变量名不能以数字开头,所以它必须是一个常量。这使得解析更容易和更严格(1000k可以很容易地发现拼写错误)。为变量和函数名称制定单一规则也更容易,因为函数也可以被视为变量。当然,现在解析器更加复杂和强大,我们在 C++ 中有自定义字面量之类的东西。但是回到史前时代,牺牲一点不必要的灵活性可能会使您的编译(或解释)时间更短(而且人们仍然抱怨 C++ 编译时间)。

并且您可以在整个 shell 语言中看到 C 影响的影响,因此 Bourne shell(或 C shell)以及 POSIX 将允许名称的类别限制为与 C 的名称类别相同也就不足为奇了。

  • 随着*解释*的进行,这是正确的。*并非*相同的考虑适用于所有语言,或者 Bourne 风格的 shell 的语法类似于 C 的语法,但与 C 相关的文化很强大,shell 设计者必须提出*一些*保证允许使用哪些标识符。我认为这可以使用“您可以在整个 shell 语言中看到 C 影响的影响”的示例,因为它们之间的相似性确实*不*超过差异(例如,考虑哪些数字被认为是*真*) . 尽管如此,这个答案是正确的。 (2认同)