2011年10月15日土曜日

MATLAB の無名関数で複数の文を実行する方法

通常 MATLAB では関数を定義する際に別ファイルを作成せねばならず,これは結構面倒です.
無名関数を使うと
f = @(x) x^3-x;
ezplot(f,[-2,2])
のように簡単な関数をその場で定義できますが,複数のステートメントを含む関数を書くことは簡単ではありません.
ここでは複数の文を含む無名関数を定義するために僕が使っているテクニックを紹介します.

複数の文を含む無名関数を書く場合,「任意の数の式を引数とし,最後の式の値を返す関数 progn 」を定義しておくと便利です.
progn = @(varargin) varargin{end};

f = @() progn(...
    figure(1),    ...
    ezplot(@sin), ...
    figure(2),    ...
    ezplot(@cos) );

f();

上の例では複数の図のプロットを行う関数を定義しています.

ただし,この方法では値を返さない関数や文を並べることができません.たとえば hold on などがこれに該当します.どうしてもこれらの関数を使いたい場合,邪道ですが evalc を使うことで問題を回避できます.
progn = @(varargin) varargin{end};

f = @() progn(...
    figure(1),      ...
    ezplot(@cos),   ...
    evalc('hold on'), ...
    ezplot(@sin));

f();

また,MATLABの無名関数はローカル変数を持つことができませんが,evalc と組み合わせると引数に対応する変数をローカル変数として利用することが可能です.
progn = @(varargin) varargin{end};

% 二番目に大きい固有値を返す関数を定義
eig_2nd = @(x) feval(@(x,e,idx) ...
    progn( ...
        evalc('e=eig(x);'), ...
        evalc('[~,idx]=sort(abs(e));'), ...
        e(idx(2))), ...
    x,0,0);

A=[4,0,0;
   0,1,0;
   0,0,2];
eig(A)
eig_2nd(A)
見てのとおり邪道で,書き捨てのプログラム以外で使うことは憚られますが,これを使うとかなり広範な関数をその場で定義できます.

0 件のコメント:

コメントを投稿