2016-08-15 2 views
2

я написал функцию тестирования, и побежал в неприятности с inputParserinputParser проверки аргумент не действует, как ожидалось

function doit(varargin) 
p = inputParser; 
p.KeepUnmatched = 1; 
% why does this bomb if I put in @ischar ? 
p.addOptional('shape','forgot',@(x) true); 
p.addParameter('color', 'k', @(x) true); % 'cause color could be char or triplet 
p.parse(varargin{:}); 
% more code using the parsed inputs 
end 

Если я бегу

doit('hello','color','g') 

или

doit('color','g') 

с кодом как и выше, все работает так, как ожидалось. Но если изменить проверку входных данных для optional аргумента p.addOptional('shape', 'forgot',@(x) ischar), я получаю сообщение об ошибке при p.parse(varargin{:})

No value was given for 'g'. Name-value pair arguments require a name followed by a value. 

Похоже, я не понимая, что последний аргумент, анонимная функция, которая должна подтвердить ввод аргумент. В чем проблема?

редактировать:

Matlab 2015a на Win7.

редактировать 2: вариационные Тестовые

Представляется, что именно то, что класс каждый аргумент в varargin это влияет на поведение.

function threeout = argthree(varargin)  
p = inputParser; 
p.KeepUnmatched = true; 
%defshape = 'forgot'; 
defshape = 5; 
addOptional(p,'shape',defshape,@isnumeric); 
addParameter(p,'color', 'k',@ischar); % 
parse(p, varargin{:}); 
threeout = p.Results; 
end 

Есть как минимум две вещи, которые могут привести к сбою анализа(). Во-первых: это:

>> argthree('nono','color','vu') 
Error using argthree (line 10) 
No value was given for 'vu'. Name-value pair arguments require a name followed by a value. 

Обратите внимание, что даже если Optional «форма» должна быть проверена на числовой, анализатор появляется думать «Ноно» является началом пары имя-значение.

Entering either a numer or nothng works: 
>> argthree('color','vu') 
ans = 
color: 'vu' 
shape: 5 
>> argthree(7,'color','vu') 
ans = 
color: 'vu' 
shape: 7 

Теперь замените строку addOptional без проверки: addOptional(p,'shape',defshape);

Получите те же результаты, что и выше для всех трех вызовов.

Теперь измените значение по умолчанию для defshape = 'forgot' % a charstring

>> argthree('nono','color','vu') 
Error using argthree (line 10) 
No value was given for 'vu'. Name-value pair arguments require a name followed by a value. 
>> argthree('color','vu') 
ans = 
color: 'vu' 
shape: 'forgot' 
>> argthree(7,'color','vu') 
ans = 
color: 'vu' 
shape: 7 

Теперь попробуйте проверки входной строки: замените строку addOptional снова- addOptional(p,'shape',defshape,@ischar);

>> argthree('nono','color','vu') 
ans = 
color: 'vu' 
shape: 'nono' 
>> argthree('color','vu') 
Error using argthree (line 10) 
No value was given for 'vu'. Name-value pair arguments require a name followed by a value. 
>> argthree(7,'color','vu') 
Error using argthree (line 10) 
The value of 'shape' is invalid. It must satisfy the function: ischar. 

Там что-то очень непоследовательно здесь с тем, как parse() пытается сопоставьте varargin{:} с списком параметров (необязательная или пара имя-значение). Из-за несогласованных сбоев, я не могу настроить ситуацию с необязательным аргументом char, за которым следует пара имен и значений, насколько я могу видеть.

обновление

Я подал отчет об ошибке в MathWorks, «Техническая поддержка Case # 02121531», и они были в состоянии воспроизвести проблему.

+0

что делать, если вы повторяете x в анонимном fcn? 'p.addOptional ('shape', 'forget', @ (x) ischar (x))' – Trogdor

+0

, какую версию Matlab вы используете? – Trogdor

+1

Он также выглядит как inputParser имеет проблемы с смешиванием addOptional и addParameter. В этом примере addOptional кажется обязательным 1-м входным аргументом (в 2015b) – Trogdor

ответ

1

Я обсуждал это с MathWorks, Службой технической поддержки № 02121531.

я написал объяснение того, что именно я надеялся сделать:

Я хотел бы быть в состоянии иметь один необязательный аргумент, который является строкой символа, а затем один или несколько пар Value-параметров , для , параметры которого являются строками. Так как я интерпретировал «факультативный», как быть только что, то есть одна из varargin {:} элементы, которые не должны присутствовать, я ожидаю, что оба из следующих команд будет работать:

foop =parseCheck('nono','color','vu');

и

foop =parseCheck('color','vu');

Однако функция анализатор оказывается не в состоянии понять, что «" цвет»является Значение в Значение параметра-р воздух. Парсер видит строку символов в качестве первого varargin и сразу же идентифицирует ее как необязательный параметр . Я считаю, что это не интуитивно и не желательно.

Я думаю, что это ошибка, и рекомендовал бы, что код парсера будет переписать так, что любая строка, которая является соответствие любому «Value» строки быть первым протестирован, чтобы увидеть, если это приводит к действительному Value-параметр pair и , только после этого должны быть проверены исходные элементы varargin {:} против дополнительной проверки аргумента.

В принципе, я говорю, что вы не можете вызвать аргумент «Необязательный», если для корректного функционирования анализатора должно присутствовать .

Последнее, что я обнаружил есть, со ссылкой на их лицо поддержки,

Спасибо за ваше терпение, пока я исследовал этот вопрос. В пример, который вы отправили, «цвет» действительно потребляется как необязательный аргумент «Форма» . Это происходит потому, что в настоящее время аргументы positional имеют приоритет над парами имя/значение. Извиняюсь за неудобства, которые могут вас причинить. Я поделился вашим документооборотом, проблемы и ваши предложения с разработчиками и усовершенствование запрос был отправлен. Это должно рассматриваться в будущих выпусках MATLAB.

1

Т.Л., др попробовать @ischar или @(x) ischar(x) вместо @(x) ischar

Объяснение:

Я подозреваю, что сообщение об ошибке не подходит, и это лишь общая ошибка, которая приводит от вашей функции проверки, выдающей ошибку. Matlab обеспечивает два типа функции проверки:

  • Один, который возвращает истина/ложь, и в этом случае генерируется соответствующая ошибка
  • или тот, который просто F *** S и генерирует исключение, в который не обрабатывается.

Я подозреваю, что в последнем случае Matlab просто выдает общее сообщение о неинформативном ошибке о том, что вы не смогли передать соответствующие параметры.

Я думаю, ваша проблема, вероятно, что внутри анонимной функции, вы фактически вызова ischar (который является функцией имя) без аргументов, что приводит к ошибке. Это порождает исключение, и Matlab интерпретирует это так, как если бы ваша функция проверки сделала исключение сигналом о том, что синтаксический анализ завершился неудачей.

Поэтому замените @(x) ischar на @ischar или @(x) ischar(x) (которые являются действительными дескрипторами функций, соответствующими функциям с одним аргументом), и он должен работать (при условии, что нет других ошибок).

+0

Nope - попробовал это, получив такое же сообщение об ошибке. –

+0

Когда я пытаюсь выполнить код с этим изменением, он работает. Вы делаете что-то другое? Также обратите внимание, что 'doit ('color', 'g')' терпит неудачу не из-за теста проверки, а потому, что 'color' интерпретируется как необязательный аргумент формы, а затем ваша ошибка означает, что у вас нет свойства, определенного в соответствии с name '' g''. –

+0

Параллельный ключ/пара значений не может появляться при отсутствии необязательного аргумента при вызове функции, поскольку необязательные аргументы - * positional *. Вы не можете перейти прямо к параметрам, иначе первый «ключ» будет интерпретироваться как необязательный аргумент «shape», и это приведет к ошибке. –

0

На самом деле это не ошибка. Это проблема с вашими функциями проверки, которые не являются достаточно конкретными. Использование только ischar в качестве функции проверки означает, что имя параметра может быть неверно истолковано как допустимое значение. По всей видимости, я ожидал бы, что ваши входы будут иметь фиксированный набор допустимых значений, и вместо этого вы должны проверить, что вход является действительным членом этого набора. Вот пример:

p = inputParser; 
addOptional(p, 'shape', 'forgot', @(s) ismember(s, {'square', 'circle', 'triangle'})); 
addParameter(p, 'color', 'k', @(c) ismember(c, 'ymcrgbwk')); 

Вы можете сделать ваши функции проверки более сложными по мере необходимости, вероятно, предшествующее anonymous functions для function handles в local functions вместо. Например, вы можете проверить тип данных , затем проверить значения, или вы можете проверить, что аргумент 'color' равен a single character or an RGB triplet.

Отчасти из-за того, что могло вызвать путаницу, вы устанавливаете 'KeepUnmatched' в true, в котором будут храниться несогласованные пары пара-парадов, а не вызывать ошибки относительно них, не соответствующие ожидаемым параметрам вашего inputParser object. Первый пример вашего второго редактирования (с использованием numeric, используемого в качестве функции проверки) не находит числовое значение в списке входных аргументов, таким образом устанавливая значение 'shape' по умолчанию. Поскольку в дальнейшем парсер ищет пару параметра-параметра, строки 'nono' и 'color' становятся непревзойденной парой и сохраняются в свойстве 'Unmatched' объекта парсера. Все еще ищет допустимую пару параметра-параметра, синтаксический анализатор находит только 'vu', который считается непревзойденной строкой параметра.

Общее правило, которым я придерживаюсь: Сделайте свои функции проверки как можно более конкретными.

+0

Ваш совет хорош, но я не уверен в вашем заключении. Дело в том, что I * не может * сделать функцию проверки более конкретной и по-прежнему допускать различные входы, которые я хочу обработать. Следовательно, соглашение MathWorks о том, что текущее состояние дел является ошибкой. –

+0

Я получаю то, что вы говорите в своем заявлении в MathWorks, и есть обоснованность аргумента, который вы делаете, но тот факт, что вы * не можете * сделать ваши функции проверки более конкретными, - это, честно говоря, красный флаг для меня , Наличие части кода, допускающего такие открытые варианты ввода, дает мне ощущение, что существует потенциальная ошибка в дизайне способа определения и/или использования этих опций. Только мои 2 цента; очевидно, я не знаю столько о вашем коде, как вы. – gnovice