数値関数名が許可されないのはなぜですか?


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

基本的に、私は関数を宣言しようとしていた10されことのための速記だろうtruefalse、しかし、あなたが見ることができるように私は関数で、数値の名前を使用して問題に遭遇しました。エイリアスと2桁の名前でも同じ動作が発生します。

質問は「なぜ」ですか?それはPOSIXによって義務付けられていますか?それとも、ボーンのような貝殻の奇妙なことですか?

これに関連する質問も参照してください。


1
posixによって義務付けられているものは、ほとんどの場合、ボーンのようなシェルの奇妙なものです。:P
muru

あなたがそこで何をしたかわかる 。。。> :) lol
セルギーコロディアズニー

4
@fkraiemを参照してくださいmeta.askubuntu.com/q/13807/295286 シェル/シェルスクリプトであり、常にUbuntuのASKに話題にされている:)これは、任意のUbuntuシステムの適切なシステム管理に不可欠なトピックだ
Sergiy Kolodyazhnyy

4
それの価値は、それは注目に0あるtrueシェルスクリプトにして1false(実際に、任意の非ゼロがfalseとして扱われる)、場合にはこれを読んで、誰もが認識していません。これは、他のほとんどのプログラミング言語とは逆です。
イーサンカミンスキー2017年

2
@EthanKaminskiはい、コマンドの終了ステータスに関する限り、それは完全に本当です。0の戻り値はtrueシェル内にあります。ただし、算術展開では、$((...))戻りステータスが反転します。1はCの構文との一貫性を保つためtrue、1は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はその理由を完全には述べていませんが、「標準のため」の回答として取り上げます。ありがとう
Sergiy Kolodyazhnyy 2017年

4
@SergiyKolodyazhnyyそれは継承されたものだと思います。この名前の標準は、他の点でもかなり一般的です(IIRC Cの名前も同じ標準に従います)。したがって、おそらくUnixのものです。また、Cでは、解析が簡単になります
muru '19

3
@muru in Cは、許可されている場合、あいまいさをもたらします。たとえば、どういう1L意味ですか?関数名?それともlong int文字通り?
ルスラン

2
上記に加えて、Cでは裸の関数名がその関数へのポインターとして機能できることに注意してください。これにより、関数をパラメータとして関数に渡したり、それらへの参照を変数に格納したりできます。コールバックによく使用されます。これは、関数名の後にが続く()可能性があります。これには、問題の関数への呼び出しを示します(呼び出されている関数によって返される値を受け取ります)。したがってint f() { return 42; }、Cに関数fがあり、ポインターコンテキストでf()有効であり、非ポインター整数コンテキストで有効である場合。
CVn 2017年

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

ご覧のとおり、数値が変数名または関数名として許可されている場合、プログラムで後で計算を行うと非常に混乱する可能性があり、それらの数値を後で実際に計算する必要がある場合は、創造的な回避策を考え出す必要があります。また、一部の言語では予期しない結果が生じる可能性があります。ループの数値をインクリメントしているが、数字の1つがすでに文字列と等しい変数であるとします。すぐにエラーがスローされます。あなたがコードの最初の作者でない場合、そのエラーを見つけるのにかなりの時間がかかる可能性があります。

簡単に言えば、これがほとんどの言語で、変数、関数、メソッドなどの名前として数値を使用できない理由です。


私はコメントするつもりだった「が、シェルを必要としている変数が前に付加されるように$展開されるため、」しかし、その後、再びシェルは他の言語に触発された場合、OK Iの推測だことに加え、算術拡張に((変数が有力持つ必要はありません$。OK、私はそれを理解できる
セルギー・コロディアズニー

3
はい、ほとんどすべての言語で予期しない結果が生じるため、これは慣例ですが、それが機能する状況であっても、あなたの後にあなたのコードに取り組む必要があるだれでもコードを理解するのが非常に困難になる可能性があります。
ジョシュ

2
@SergiyKolodyazhnyy算術展開では$、なしで変数名を参照できるため、それがあります。しかし、それはおそらく「一般的な慣習に従うだけ」という他の理由の二次的なものです
ホッブズ

@ホブスうん、絶対にそれに同意する
セルギー・コロディアズニー

1
この「ほとんどの言語」の説明は、シェルにはほとんど意味がありません。すべてのボーンスタイルのシェルは、名前のパラメータ持つように見える数値リテラルや演算子を:0シェルまたはスクリプトの名前について、12、...、位置パラメータのために、*彼らが参加するために、-有効なオプションについては、?前回の終了ステータスのために、と!のために最新の非同期ジョブのPID。(したがって、でも中に$(( ))$しばしば必要とされている。)そのように実証する方法はありませんので、として提案根拠を示すために、ここに示すコードは、任意のボーンスタイルのシェルのスクリプトではありません、それは適用されませんにそれら。
Eliah Kagan 2017

10

Cでは、次のような式を考えます。

1000l + 2.0f;

ある1000l変数または定数?変数名は数字で始めることはできないため、定数でなければなりません。これにより、解析がより簡単かつ厳密になります(タイプミス1000kは簡単に検出できます)。関数も変数として扱うことができるので、変数と関数名の単一のルールを持つ方が簡単です。さて、もちろん、パーサははるかに複雑かつ強力であり、そして我々は、C ++でカスタムリテラルのようなものを持っています。しかし、それらの先史時代に戻って、不要な柔軟性を少し犠牲にすると、コンパイル(または解釈)時間が大幅に短縮される可能性があります(C ++のコンパイル時間については不満があります)。

また、シェル言語全体でCの影響の影響を確認できるため、Bourneシェル(またはCシェル)、したがってPOSIXがCと同じ名前に許可された名前のクラスを制限していることは驚くに値しません。


2
説明が進むにつれ、これは正しいものです。それはだではない、同じ考慮事項がすべての言語に適用することまたはBourneスタイルのシェルはCと同様の構文を持っていることが、Cに関連した文化が強いとシェルデザイナーが思い付くしなければならなかったことがいくつかの識別子がどうなるかにとして保証許可されています。これは、「シェル言語全体でCの影響の影響を見ることができる」という例を使用できると思います。両者の類似性は実際に違いを上回らないためです(たとえば、どの数値がtrueと見なされるかについて考えてみてください)。それにもかかわらず、この答えは正しいです。
Eliah Kagan

@Eliah間違いなく、数値はCの成功と失敗の終了ステータスの直接の結果でもあるため、シェルテストを作成するときは、真と偽ではなく、成功と失敗の観点から考える傾向があります。あなたのシェル構文の豊富にいる権利は、Cのようなものは何もありませんが、例は中括弧、セミコロンを含める短絡&&||、文字列内のASCII NULのためのサポートの欠如、
Olorin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.