14

私は(驚いたことに)次の関数を呼び出すことを発見しました

function foo()
if false
   fprintf = 1;
else
  % do nothing
end
fprintf('test')

与えるとエラーUndefined function or variable "fprintf"。私の結論は、変数のスコープは実行前に決定されるということです(コンピューター言語、特にMatlabの解釈がどのように機能するかについての私の限られた理解では)。誰かが私にこれに関するいくつかの背景情報を教えてもらえますか?

編集

私が上で言及するのを忘れたもう一つの興味深いことはそれです

function foo()
if false
   fprintf = 1;
else
  % do nothing
end
clear('fprintf')
fprintf('test')

を生成しReference to a cleared variable fprintfます。

4

4 に答える 4

9

MATLABは、実行される前に関数を解析します。たとえば、変数をアクティブ化する(またはアクティブ化しない)分岐に関係なく、変数名を検索します。つまり、スコープは実行時に決定されません。

補遺:これを行うことはお勧めしませんが、MATLABを使用してお勧めできないことをしている人をたくさん見ました。しかし...誰かが「false」と呼ばれる独自の関数を定義した場合にどうなるかを考えてみてください。実行前のパーサーは、その関数が呼び出された場合に何が起こるかを知ることができませんでした。

于 2012-10-25T18:27:07.160 に答える
8

MATLAB JITコンパイラが初めてmファイルを解析するときに、関数で宣言されているすべての変数を識別しているようです。上記の変数が到達不能コードで宣言されているかどうかは気にしないようです。したがって、ローカルfprintf変数はすぐに組み込み関数を非表示にしますfprintf。これは、この関数に関する限り、という名前の組み込み関数がないfprintfことを意味します。

もちろん、それが発生すると、関数内のすべての参照fprintfはローカル変数を参照し、変数が実際に作成されることはないため、それにアクセスしようとするとエラーが発生します。

変数をクリアすると、ローカル変数がクリアされます。存在する場合は、組み込み関数がスコープに戻されません。

組み込み関数を明示的に呼び出すには、builtin関数を使用できます。

builtin( 'fprintf', 'test' );

上記の行は、fprintf関数をシャドウする可能性のあるローカル変数に関係なく、常にMATLABコマンドラインでテキストを出力します。

于 2012-10-25T17:27:30.830 に答える
4

興味深い状況。この奇妙なケースに関してMATLABインタープリターがどのように機能するかについての詳細な情報があるかどうかは疑問ですが、ドキュメントには注意すべき点がいくつかあります...

MATLABで使用される関数の優先順位は、変数を最初に配置します。

名前が関数と一致すると想定する前に、MATLABは現在のワークスペースでその名前の変数をチェックします。

もちろん、あなたの例でfprintfは、条件文のそのブランチが入力されることはないため、変数は実際にはワークスペースに存在しません。ただし、変数の命名に関するドキュメントには次のように書かれています。

関数と同じ名前の変数(、、、、、、、など)を作成することは避けiてください。一般に、変数名は関数名よりも優先されます。関数の名前を使用する変数を作成すると、予期しない結果が生じることがあります。jmodecharsizepath

これは、特に変数が実際に作成されていない場合は、これらの「予期しない結果」の1つである必要があります。結論として、MATLABには、実行時にファイルを解析して、特定のスコープ内に存在する可能性のある変数を判別するメカニズムが必要です。その結果、関数は、 mファイルに表示される変数によってもシャドウされる可能性があります。最終的にワークスペースに表示されない場合。


編集:さらに厄介なのは、関数が影になっているように見えるという事実のように機能し、それを認識していないことですexistwhichを呼び出す前にこれらの行を追加しますfprintf

exist('fprintf')
which('fprintf')

エラーが発生する前にこの出力を提供します。

ans =
     5
built-in (C:\Program Files\MATLAB\R2012a\toolbox\matlab\iofun\fprintf)

ビルトインがまだ表示されていることを示しfprintfます。

于 2012-10-25T17:14:38.600 に答える
2

これらは洞察を提供するかもしれません:

これにより、シャドウされているものに関する情報が得られます。

which -all

(以下はバグとして確認されました)1つの落とし穴は、Workspace構造体、およびパス上のクラスには、(あなたが私である場合)あなたを捕まえる可能性のある特定のスコープと型の優先順位があることです。

例:2017b:

% In C.m, saved in the current directory
classdef C
 properties (Constant)
   x = 100;
 end
end

% In Command window
C.x = 1;
C.x       % 100
 C.x      % 1 (Note the space)
C.x*C.x   % 1
disp(C.x) % 1
于 2018-05-09T18:40:31.037 に答える