zshでpathという読み取り専用変数を定義できないのはなぜですか?

zshでpathという読み取り専用変数を定義できないのはなぜですか?

zshでは、path内容はよく知られている変数に関連付けられている特別な配列変数ですPATH

実際、この関数を定義して呼び出すことは非常に特別です。

f() { local -r path=42 }

エラーが発生しますf: read-only variable: path。ローカル変数が変更可能であると宣言されると(つまり、not -r)、すべてが期待どおりに機能します。別の変数名を使用すると、このエラーを再現できません。

このエラーはなぜ発生しますか?意図的なことでしょうか?他の名前にも同様の規則がありますか?

私はmacOS 10.12.6でzsh 5.2(x86_64-apple-darwin16.0)を使用しています。

ベストアンサー1

TL;DR「特別な組み込みパラメータ」を再使用しないでくださいpath。または、メーリングリストこの-hフラグは次のように使用できます。

% () { local -hr path=42; echo $path }
42
% 

(しかし、整数に変更すると、このオーバーライドを忘れてしまう...と仮定するpath後続のコードが混乱する可能性があります。)pathpath

より長い発掘が続きました(しかし-h隠されたものを完全に逃しました...)

% print ${(t)path}
array-special

これは特殊変数(関数?エラー?)の属性ですが、ユーザーリンクの同様の変数ではありません。

% () { typeset -r PATH=/blah; echo $PATH }
(anon): read-only variable: PATH
% typeset -Tar FOO=bar foo
% print $foo
bar
% print ${(t)foo}
array-readonly-tag_local
% () { local -r foo=blah; echo $foo }
blah

この動作を表すさまざまなパラメータがあります。

% for p in $parameters[(I)*]; do print $p $parameters[$p]; done | grep array-
cdpath array-special
...
% () { local -r cdpath=42 }
(anon): read-only variable: cdpath

したがって、いくつかの変数は次のようになります。動物農場他の人よりも特別です。このエラーメッセージはさまざまな場所で発生し、その中でSrc/params.cコンパイル時に見つかったメッセージが特定であるかどうかを印刷するように修正すると、次のようになりますzsh

% () { local -r path }
% () { local -r path=foo }
(anon): read-only variable (setarrvalue): path

かなり一般的なコードです

/**/
mod_export void
setarrvalue(Value v, char **val)
{
    if (unset(EXECOPT))
        return;
    if (v->pm->node.flags & PM_READONLY) {
        zerr("read-only variable (setarrvalue): %s", v->pm->node.nam);
        freearray(val);
        return;
    }

これは、問題が他の場所で発生することを示します。非特殊変数は間違いなくPM_READONLY設定されていませんが、失敗した特殊変数は設定されました。次に注目すべき点は、localさまざまな名前(...)を持つコードですtypeset export。これらはすべて組み込まれているので、画面に何が隠れているかを見つけることができます。Src/builtin.c

% grep BUILTIN Src/builtin.c | grep local
    BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%ahi:%lp:%rtux", NULL),

これはbin_typesetさまざまなフラグを設定する呼び出しなので、関数のソースコードを見てみましょう。コメントで誓い、確認してください。状況が複雑なので確認してみてください。ウサギの洞窟にもかかわらず(「パラメータをパターンとして処理」-mオプションが選択されている場合)いいえset、ここの場合)このtypeset_single関数の結果のようです...

POSIXBUILTINS関連するコードがありますが、readonly私のテストシェルでは閉じています。

% print $options[POSIXBUILTINS]
off

だから私はそのコードを無視します。同時に!一部のデバッグポイントは、次の行でPM_READONLYフラグがオンになっていることを示します。path

    /*
     * The remaining on/off flags should be harmless to use,
     * because we've checked for unpleasant surprises above.
     */
    pm->node.flags = (PM_TYPE(pm->node.flags) | on | PM_SPECIAL) & ~off;

これはon、関数を入力したときにすでに開いている変数からのものです。ため息、始まった場所typeset_singleに戻ります...まあ、デフォルトでは、ユーザーが次のように変数を提供したときに、代わりにいくつかのマクロを介してデフォルトで有効になる変数があります。 thisコードパスが実行されると、変数はオフになり、すべてがうまく機能します。bin_typesetTYPESET_OPTSTRPM_READONLYPM_READONLY

pathたとえば、特殊変数が読み取り専用になるように(zsh-workersメーリングリストを使用してみてください)、そうでなければその間に特殊変数を操作しないように変更できるかどうかはZSH開発者に質問です。

おすすめ記事