5

と呼ばれる単一の最上位関数を含む MATLAB ファイルがありますsandbox。その関数には、2 つの入れ子になった関数 と が含まれてmysumいます。これらは機能が同じであり、許可されるパラメーターは、一方が内部で使用され、他方が内部でmyprod使用されることを除いて同じです。私の目標は、両方で使用するラッパー関数を作成し、すべての検証と入力解析を処理することです。この機能は と呼ばれます。@sum@prodmysummyprodapplyFunc

ここがややこしいところです。次の 2 つの形式がmysumあります。myprod

  1. mysum(v)戻りますsum(v, 1)
  2. mysum(v, 'imag')戻り値sum(v, 1) + 1i

入力の他の組み合わせは、エラーをスローする必要があります。

inputParserこれらのさまざまな入力の組み合わせ、特にオプションの文字列入力を解析するのに問題があります。コードは次のとおりです。

function sandbox()
%% Data
v = [1 4; 3 3];

%% Calculations
s = mysum(v);
si = mysum(v, 'imag');
p = myprod(v);
pi = myprod(v, 'imag');

%% Accuracy tests
assert(isequal(s, [4 7]))
assert(isequal(si, [4+1i 7+1i]))
assert(isequal(p, [3 12]))
assert(isequal(pi, [3+1i 12+1i]))

    function x = mysum(varargin)
        x = applyFunc(@sum, varargin{:});
    end

    function x = myprod(varargin)
        x = applyFunc(@prod, varargin{:});
    end
end

function x = applyFunc(func, varargin)

p = inputParser();
p.addRequired('func', @(x) validateattributes(x, {'function_handle'}, {'scalar'}));
p.addRequired('v', @(x) validateattributes(x, {'double'}, {}, 'applyFunc:msg', 'v'));
p.addOptional('imag', '', @(x) validatestring(x, {'imag', ''})); % THIS LINE IS THE PROBLEM
p.parse(func, varargin{:});

f = p.Results.func;
v = p.Results.v;
strflag = p.Results.imag;

x = f(v);
if ~isempty(strflag)
    validatestring(strflag, {'imag'});
    x = x + 1i;
end
end

問題の原因となっている行は次のとおりです (上記のコードでマークされているとおり)。

p.addOptional('imag', '', @(x) validatestring(x, {'imag', ''}));

inputParser のドキュメントには、次のように記載されています。

オプションの文字列入力の場合は、検証関数を指定します。検証関数がない場合、入力パーサーは有効な文字列入力を無効なパラメーター名として解釈し、エラーをスローします。

残念ながら、これを行う方法がわかりません。簡単なImが欠けているものはありますか? 'imag'引数がまったく渡されない場合( and の割り当てのようsp)、コードは正常に動作しますが、渡すと次のエラーが発生します。

Error using sandbox>applyFunc (line 32)
The value of 'imag' is invalid. It must satisfy the function:
@(x)validatestring(x,{'imag',''}).
Error in sandbox/mysum (line 18)
        x = applyFunc(@sum, varargin{:});
Error in sandbox (line 7)
si = mysum(v, 'imag'); 

何か助けはありますか?

4

2 に答える 2

5

問題は、検証に合格したかどうかを示すブール値ではなくvalidatestring、セル引数 ( ) から一致する文字列を返すことです。{'imag',''}代わりに、およびを使用strcmpanyます。

@(x) any(strcmp(x,{'imag', ''}))

また、 では、入力文字列がまたはvalidatestringのいずれにも一致しなかった場合(実際には空の文字列は R2014a+ でのみ一致するため)、 が適切なエラーを返すことができるように、false を返すのではなくエラーをスローします。'imag''''imag'inputParser

この問題を解決するもう 1 つの良い方法は、 の構文をapplyFunc完全に変更し'imag'て、オプションの文字列入力引数の代わりに、パラメータとしてParameter-Valueを使用'imag'し、検証されたブール値を入力として使用することです。

コメントで Amro によって提案された入力定義:

p.addParameter('imag', false, @(x)validateattributes(x, {'logical'}, {'scalar'}))

使用法:

mysum(x,'imag',true)
mysum(x)               % default is equivalent to mysum(x,'imag',false)

これにより、残りのコードがスカラーで単純化p.Result.imagされlogicalます。私は提案します:

x = f(v) + p.Result.imag*1i;
于 2013-12-17T23:19:12.997 に答える
2

問題は ではありません。問題はinputParserにあると思いますvalidatestring

1) まず、空の文字列には一致しません:

>> x = ''
x =
     ''

>> validatestring(x, {'imag',''})
Expected input to match one of these strings:

imag,

The input did not match any of the valid strings.
Caused by:
    Error using validatestring>checkString (line 85)
    Expected input to be a row vector. 

2) 次に、一致に成功した場合は、true/false ではなく、(有効な選択肢の 1 つから) 解決された文字列を返します。inputParser検証関数がブール値を返すか、失敗時にエラーをスローするだけである必要があります。

于 2013-12-17T23:21:03.187 に答える