関数は、自分が「再定義」する関数をどのように呼び出すのですか?

関数は、自分が「再定義」する関数をどのように呼び出すのですか?

たとえば、fpath次のように設定されているとします。

( $HOME/.zsh/my-functions /usr/local/share/zsh/site-functions )

...そして関数定義ファイル$HOME/.zsh/my-functions/quuxとその両方が/usr/local/share/zsh/site-functions/quux存在します。

quux(これら2つのバージョンをそれぞれ「ユーザーのquux」バージョンと「サイトの」バージョンと呼びますquux。)

さらに、私が走ったと仮定すると

autoload -U quux

つまりquux、今実行すると、ユーザーのquux

この記事のタイトルの「オーバーレイ」という言葉は、この場合、ユーザーのquuxサイト「オーバーレイ」を意味しますquux。 (「オーバーレイ」の代わりに「シャドウ」と言うこともできます。)


quux私の質問は:ユーザーがウェブサイトを順番に呼び出す方法はありますかquux? (通常、ユーザーはquuxサイトに渡されたパラメータを処理するquuxか、サイトで生成された出力を処理します。)

私は何も修正する必要のないソリューションを探しています/usr/local/share/zsh/site-functions/quux

重要:fpathこの質問に使用されたもの単なる例。一般的に私たちが知っているのは、他fpathの関数をオーバーライド(シャドウイング)して関数にアクセスできることです。


私は$HOME/.zsh/my-functions/quux一般的な形で卑劣な計画を試しました。

# one-time initialization
local body
body=$( SOMEHOW <???> GET SOURCE CODE OF OVERRIDDEN FUNCTION )
eval "overridden_quux () {
$body
}"

# self-re-definition (MWAH-HA-HA-HA-HAAAA!)
quux () {
    local massaged_args
    massaged_args=( $( MASSAGE ARGS "$@" ) )
    __overridden_quux "$massaged_args" | MASSAGE OUTPUT
}

# one-time re-invocation
quux "$@"

...しかし、方法が醜いことは言うまでもなく、結果も非常に脆弱です。

答え1

最も簡単な方法は、.zshrc同じ名前の関数を使用するのではなく、元の関数を強制的にロードして名前を変更し、fpathで再定義することです。 zshでは、関連する複雑なトリックは必要なく、which名前eval変更関数への参照を考慮する必要もありません。functions連想配列

autoload -Uz +X quux
functions[overridden_quux]=$functions[quux]
quux () {
  … overridden_quux $@[@] …
}

fpathのファイルから関数を自動的にロードしたい場合は、同じfpathエントリに再帰的にアクセスせずに元のファイルをロードする必要があるため、面倒です。ローカルオーバーライドよりも優れたソリューションはありませんfpath

#autoload quux
functions[overridden_quux]=$(
    fpath=("${(@)fpath:#$HOME/*}")
    autoload -Uz +x quux
    print -r -- $functions[quux]
)
quux () {
  … overridden_quux $@[@] …
}

関連情報