関数 eval の代替方法
関数 eval の使用が好ましくない理由
eval
は非常に強力で柔軟な関数ですが、プログラミング問題において常に最適な解決方法であるとは限りません。eval
を呼び出すコードは、他の関数や言語要素を使用するコードに比べて効率が低く、読み取りやデバッグが難しいことがあります。以下に例を示します。
MATLAB® では、後の実行パフォーマンスを向上させるため、初回実行時にコードをコンパイルします。しかし
eval
ステートメント内にあるコードは、実行時に変更される可能性があるためにコンパイルされません。eval
ステートメント内のコードによって、現在のワークスペースに既に存在する変数が作成されたり、こうした変数に値が代入されるなどの予期しない動作が発生し、既存のデータが上書きされる可能性もあります。eval
ステートメント内の文字ベクトルを連結すると、コードが読みづらくなることがあります。他の言語要素を使用してコードの構文を簡易化できます。
eval
の一般的用法の多くは、以下の例に示される手法で代替することが推奨されます。
連番が含まれる名前をもつ変数
関数 eval
は、A1
、A2
、...
、An
といった一連の変数を作成するためによく使用されますが、この方法では MATLAB の配列処理機能が活かされず、これを推奨することはできません。望ましい方法は、関連するデータを 1 つの配列に格納することです。データ セットに含まれるデータの型やサイズが一定でない場合は、構造体または cell 配列を使用します。
たとえば、10 個の要素を含み、その各要素が数値配列である cell 配列を作成します。
numArrays = 10; A = cell(numArrays,1); for n = 1:numArrays A{n} = magic(n); end
この cell 配列内のデータにアクセスするには、中かっこのインデックスを使用します。たとえば、A
の 5 番目の要素を表示するには、次のようにします。
A{5}
ans = 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9
代入ステートメント A{n} = magic(n)
を使用する方が、次の eval
呼び出しよりも効率がよく、洗練されています。
eval(['A', int2str(n),' = magic(n)']) % Not recommended
詳細については、以下を参照してください。
連番が含まれる名前をもつファイル
関連するデータ ファイルの名前は、たとえば myfile1.mat
~ myfileN.mat
などのように、共通のルート名と整数インデックスで構成される場合がよくあります。関数 eval
の一般的な用法として、次のようなコマンド構文を使用して各ファイル名を構成し、関数に渡すことがありますが、これは推奨できません。
eval(['save myfile',int2str(n),'.mat']) % Not recommended
変数を入力として渡せる関数構文の使用をお勧めします。以下に例を示します。
currentFile = 'myfile1.mat';
save(currentFile)
関数 sprintf
を使用してループ内でファイル名を作成し (これは通常 int2str
よりも効率的です)、その後 eval
を使わずに関数 save
を呼び出すことができます。次のコードでは、現在のフォルダーに 10 個のファイルが作成されます。
numFiles = 10; for n = 1:numFiles randomData = rand(n); currentFile = sprintf('myfile%d.mat',n); save(currentFile,'randomData') end
詳細については、以下を参照してください。
変数に含まれる関数名
eval
は、関数の名前が変数文字ベクトルに含まれる場合、その関数を実行するためによく使用されます。変数から関数を評価するには、eval
を使用するよりも効率的な方法が 2 つあります。
@
記号または関数str2func
を使用して関数ハンドルを作成します。たとえば、cell 配列に格納されたリストから関数を実行します。examples = {@odedemo,@sunspots,@fitdemo}; n = input('Select an example (1, 2, or 3): '); examples{n}()
関数
feval
を使用します。たとえば、実行時に指定されるデータを使ってプロット関数 (plot
、bar
、pie
など) を呼び出します。plotFunction = input('Specify a plotting function: ','s'); data = input('Enter data to plot: '); feval(plotFunction,data)
変数に含まれるフィールド名
可変のフィールド名をもつ構造体のデータにアクセスするには、フィールドの式を小かっこで囲みます。以下に例を示します。
myData.height = [67, 72, 58]; myData.weight = [140, 205, 90]; fieldName = input('Select data (height or weight): ','s'); dataToUse = myData.(fieldName);
入力プロンプトで weight
と入力した場合、次のコマンドで weight
の最小値を取得できます。
min(dataToUse)
ans = 90
その他の例は、変数からフィールド名を生成 を参照してください。
エラー処理
MATLAB でエラー処理を行うには、try, catch
ステートメントの使用が推奨されます。以下に例を示します。
try B = A; catch exception disp('A is undefined') end
ワークスペースに変数 A
がない場合、このコードでは次が返されます。
A is undefined
関数 eval
に関するドキュメンテーションの以前のバージョンには eval(expression,catch_expr)
構文が含まれています。expression
の入力を評価してエラーが返された場合は、eval
によって catch_expr
が評価されます。ただし、eval
ステートメントで暗黙的にキャッチするよりも、明示的な try/catch
を使用する方がはるかに明確です。暗黙的なキャッチの使用は推奨できません。