web-dev-qa-db-ja.com

vararginとvarargoutを使用して関数をラップする方法は?

ミニ例:

_function varargout = wrapper(varargin)
varargout = someFunction(varargin);
_

それが私が最初にそれをする方法です。ただし、たとえば_someFunction = ndgrid_の場合、セル配列に対して未定義のエラーが発生するため、次の試行では代わりにsomeFunction(varargin{:})を使用しました。これは成功した呼び出しですが、[a,b] = wrapper([1,2], [3,4])を呼び出しても、ndgridを直接呼び出した場合と同じ結果は得られないので、何が間違っているのでしょうか。

31
Tobias Kienzler

実際、ミハイルの答えは完全には正しくありません。 someFunctionが、何も要求されなくても値を返す関数である場合、これは、関数が値をansに割り当てる必要があることを示す方法であり、Mikhailのラッパーは失敗します。たとえば、someFunctionがsinに置き換えられ、ラッパーの実行とsinの直接実行を比較すると、次のようになります。

>> wrapper(0)
>> sin(0)

ans =

   0

これを行う正しい方法は

function varargout = wrapper( varargin )
[varargout{1:nargout}] = someFunction( varargin{:} ); 

これが機能する理由は、MATLABインデックスルールのほとんど知られていないEdgeケースが、少なくともR2006a(おそらくそれより長い)以降、このケースに対して正確に存在しているためです。これはMATLABインデックス作成のいぼのようなものですが、この種のことを処理するために必要であると見なされました。

ルールは次のとおりです。

添え字付き代入を実行する場合、

  • 添え字付き-初期化されていない変数への割り当て、および
  • 初期化されていない変数には中括弧のインデックスが付けられ、AND
  • 中括弧内のインデックスは空であり、AND
  • 左側は角括弧の内側に表示され、AND
  • 右側は値に解決されます/出力を返します

次に、初期化されていない変数には、右側から返された値を含むスカラーセルが割り当てられます。

例えば:

>> clear uninit % just to make sure uninit is uninitialized
>> [uninit{[]}] = sin(0)

uninit = 

    [0]
36
SCFrench
function varargout = wrapper( varargin )

if ~nargout
    someFunction( varargin{:} ); 
else
    [varargout{1:nargout}] = someFunction( varargin{:} ); 
end
7
Mikhail

出力引数の数が入力引数の数と同じである場合は、次を使用できます。

function varargout = wrapper(varargin)
[varargout{1:nargin}] = someFunction(varargin{:});

これはndgridで正常に機能します。

1
mburg