4

У меня есть файл MATLAB, содержащий одну функцию верхнего уровня, называемую sandbox. Эта функция, в свою очередь, содержит две вложенные функции: mysum и myprod, которые идентичны по функциональности и какие параметры они позволяют, за исключением того, что один использует @sum внутренне, а другой использует @prod внутри. Моя цель - создать функцию обертки для использования как в mysum, так и в myprod, которая выполняет все проверки и синтаксический анализ ввода. Эта функция называется applyFunc.Как использовать входной парсер MATLAB с дополнительными строковыми вводами? В документации говорится: «используйте функцию проверки», но неясно, как это сделать

Вот где это сложно. 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 говорит, что:

For optional string inputs, specify a validation function. Without a validation function, the input parser interprets valid string inputs as invalid parameter names and throws an error.

К сожалению, я не знаю, как это сделать. Есть ли что-то простенькое? Если 'imag' аргумент не передается вообще (как в назначении s и p), код работает отлично, но если я передать его, я получаю эту ошибку:

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

Проблема заключается в том, что validatestring возвращает строку соответствия из аргумента ячейки ({'imag',''}), а не логическую, указывающую, прошла ли она валидация. Вместо этого используйте strcmp и any:

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

Кроме того, с validatestring, если входная строка не соответствует ни 'imag' или '' (на самом деле просто 'imag' поскольку пустые строки совпадают только в R2014a +), она выдаст ошибку, а не возвращает false, так что inputParser может вернуть соответствующую ошибку.

Еще один хороший способ, чтобы решить эту проблему, чтобы изменить синтаксис 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; 
+3

+1 использование 'strcmp' решает проблему. Лично мне не нравятся «необязательные аргументы», я бы предпочел использовать аргумент параметра name-value: 'p.addParameter ('imag', false, @ (x) validateattributes (x, {'logical'}, {' скалярное '})) '. Тогда 'p.Result.imag' будет либо true, либо false. – Amro

+0

Это хороший способ очистить сравнение позже и в коде. Это может быть аргумент param-value с логическим значением. – chappjc

+0

@chappjc Спасибо за помощь. Мне действительно нравится использовать пару имя-значение вместо необязательного аргумента, поэтому я, вероятно, буду использовать это для нового кода. К сожалению, код Im, работающий на данный момент, является устаревшим материалом для API, который не может быть изменен. –

1

Проблема не 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) Во-вторых, если он успешно соответствует, он возвращает разрешенную строку (от одного действительного выбора), а не истина/ложь , inputParser требует, чтобы функция проверки возвращала логическое значение или ничего, кроме ошибки при ошибке.

+0

Вы видели заметки о выпуске R2014a? Кажется, теперь пустая строка совпадает. Как будто MathWorks читает так. :) – chappjc

+0

Я не видел предварительную публикацию, но это хорошая новость. Спасибо, что сообщили нам. Из любопытства, есть ли какие-либо существенные изменения в предварительном выпуске? Возможно, графика HG2? – Amro

+0

HG2 еще не по умолчанию. Когда вы нажимаете клавишу «вверх» в командной строке, возникает какая-то неприятная новая история всплывающих команд. Теперь настройка MEX проще, но с отдельными конфигурациями C и C++ (я вижу массовую путаницу в будущем). Команды 'flipud',' fliplr' и 'rot90' теперь работают с многомерными массивами, но синтаксис изменился. Некоторые новые тестовые функции, такие как 'issymmetric',' isdiag' и т. Д. – chappjc