POSIX シェルの関数と変数の別々の名前空間

POSIX シェルの関数と変数の別々の名前空間

dash では、関数と変数は別々の名前空間に存在するように見えます。

fn(){
    fn="hello world"
}
fn; echo "The value is $fn!" #prints: The value is hello world!
fn; echo "The value is $fn!" #prints: The value is hello world!
#the fn variable doesn't conflict with the fn function

これは dash 固有の機能ですか、それとも POSIX の保証ですか?

答え1

保証:

2.9.5 関数定義コマンド

関数は、新しい位置パラメータを持つ複合コマンドを呼び出すための単純なコマンドとして使用されるユーザー定義の名前です。関数は、「関数定義コマンド」で定義されます。[...]

関数の名前は fname です。アプリケーションは、それが名前 (XBD 名を参照) であり、特別な組み込みユーティリティの名前ではないことを確認する必要があります。実装では、拡張機能として関数名に他の文字を許可できます。実装では、関数と変数に対して別々の名前空間を維持する必要があります。

答え2

変数と関数はダッシュ内の異なる名前空間に存在し、これも次のように指定されます。POSIX:

実装では、関数と変数に対して別々の名前空間を維持する必要があります。

さらに、変数はデフォルトでグローバル スコープを持ちます。一部のシェル (bash、ksh、zsh など) では、local関数内でローカル スコープのみを持つ変数を宣言するためのキーワードが提供されています。

つまり、あなたが見ている動作は POSIX によって保証されています。

POSIXは標準化された localまだ:

初期の提案における関数の記述は、関数は小さなシェルスクリプトのように動作するべきであるという考えに基づいていました。つまり、変数を共有する場合を除く実行環境のほとんどの要素は、あたかも新しい実行環境であるかのように動作するはずです。[..]

[..] 関数内のローカル変数は、別の初期の提案(特別な組み込み関数によって制御されるlocal)で考慮され、含まれていましたが、削除されました関数用に開発された単純なモデルに適合せず、また、従来の慣例に含まれない新たな特殊な組み込み関数を追加することに反対する声もあったためです。実装では、このローカル変数メカニズムがこの標準の将来のバージョンで採用される場合に備えて、識別子local(およびtypesetKornShell で使用される ) を予約する必要があります。

(強調は筆者による)

関連情報