MATLAB: Использование inputParser с varargin - PullRequest
4 голосов
/ 10 февраля 2012

У меня есть функция, для которой я хотел бы передать аргументы через varargin и использовать inputParser, чтобы убедиться, что входные данные являются нормальными. Некоторые аргументы обязательны, а некоторые нет. Вот пример:

function myFunc(varargin)
    p = inputParser;
    p.addRequired(...
            'numStates', ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'scalar', 'integer', 'positive'}));
        p.addRequired(...
            'numInps', ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'scalar', 'integer', 'positive'}));
        p.addRequired(...
            'numOuts', ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'scalar', 'integer', 'positive'}));
        p.addRequired(...
            'X0', ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'vector'}));
        p.addOptional(...
            'freq', 10, ...
                @(x) validateattributes(x, {'numeric'}, ...
                {'scalar', 'integer', 'positive'}));
        p.addOptional(...
            'SimulinkVariables', struct(), ...
                @(x) isa(x, 'struct'));

    p.parse(varargin{:});

    %# do stuff with variables
end

Я бы хотел передать аргументы следующим образом; не должно иметь значения, какая пара будет передана, когда, пока есть необходимые. Таким образом, пример вызова может быть:

myFunc('numStates', 4, 'numInps', 2, 'numOUts', 3, 'X0', [4;0]);

Видимо, этот синтаксис недопустим; parse() ожидает, что первые аргументы в нем - это обязательные значения, но они не должны иметь явного имени, то есть, как в:

function myFunc(numStates, numInps, numOuts, X0, varargin)
    ...
    p.parse(numStates, numInps, numOuts, X0, varargin{:});

end

Есть ли простой способ заставить это делать то, что я хочу, то есть первую функцию? Я предполагаю, что проще всего сделать что-то, чтобы изменить порядок элементов varargin и выбросить имена аргументов, но это не очень элегантно.

Ответы [ 2 ]

7 голосов
/ 10 февраля 2012

Самое элегантное решение, которое я могу придумать, - это создать подкласс inputParser. Таким образом, вы можете сделать что-то вроде этого (сохранить как myInputParser.m):

classdef myInputParser < inputParser
    properties
        required = {};
    end

    methods
        function obj = myInputParser
            obj = obj@inputParser;
        end

        function addRequired(obj, argname, validator)
            obj.required = {obj.required{:}, argname};
            obj.addOptional(argname, [], validator);
        end

        function parse(obj, varargin)
            params_input = varargin(1:2:end);
            for i=1:length(obj.required)
                if isempty(strmatch(obj.required{i}, params_input))
                    error(sprintf('Required named parameter %s was not passed to function', obj.required{i}));
                end
            end
            parse@inputParser(obj, varargin{:});
        end

    end
end

Затем измените

    p = inputParser;

до

    p = myInputParser;

и тогда ваш код будет работать так, как вы хотите.

Обратите внимание, что это может не обрабатывать все крайние случаи правильно, и я не тестировал это подробно, но он работает с вашим примером использования.

5 голосов
/ 10 февраля 2012

В InputParser вы можете добавить ParameterName - ParameterValue только для пар с addParamValue.Эти аргументы должны быть необязательными.

В качестве обходного пути вы можете добавить все свои параметры с помощью addParamValue и использовать [] в качестве значения по умолчанию для требуемых аргументов.

Затем вы можете выполнить одно из следующих действий:

  • добавить «непустые» атрибуты в функцию validateattributes для обязательных аргументов (, однако в этом случае сообщение об ошибке будетНе говорите, что это обязательные аргументы, но это должно быть непустым )
  • или добавьте отдельную проверку (с if или assert), что требуемые аргументы должны быть непустыми с вашимсобственное сообщение об ошибке.

Вы не ограничены использованием [].Значением по умолчанию может быть любое значение, которое не подходит для определенного параметра и которое легко проверить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...