Использование функции с необязательными введенными параметрами - PullRequest
0 голосов
/ 31 августа 2018

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

Varargin не является решением этой проблемы, потому что некоторые функции INPUTS не существуют.

Рабочая область

var1 = 1
var2 = 2
var4 = 4

Код для включения в функцию

if exist('var3','var')
   disp('var 3 exists')
else
   disp('var 3 does not exist')
end

Следующая функция НЕ будет работать, потому что она вызывает переменную 3, которая не существует.

вызывающая функция

runCode(var1, var2, var3, var4)

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

  if ~exist("var1", "var"), var1= NaN; end 
  if ~exist("var2", "var"), var2= NaN; end 
  if ~exist("var3", "var"), var3= NaN; end 
  if ~exist("var4", "var"), var4= NaN; end 

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

Спасибо за любые идеи, которые вы, ребята, могли бы иметь

Ответы [ 3 ]

0 голосов
/ 02 сентября 2018

Текущий скрипт ведет себя по-разному в зависимости от наличия набора переменных с предопределенными именами. Это трудно воспроизвести в функции, потому что функция должна не читать значения вызывающей рабочей области. Это можно сделать, конечно:

try
   var1 = evalin('caller','var1');
catch
   % do nothing, the variable doesn't exist in the caller, it won't exist here
end

Но это действительно плохая практика, и ничем не отличается от сценария. И ОП специально сказал, что не хочет использовать eval.

Есть альтернатива, которую я не решаю рекомендовать, потому что она почти такая же злая, как и выше. Мы собираемся определить функцию, чьи входные аргументы основаны не на порядке, а на имени:

runCode(var1)

будет вести себя иначе, чем

runCode(var2)

Но следующие два утверждения будут вести себя одинаково:

runCode(var1,var2)
runCode(var2,var1)

Уволен? Вы должны быть!

Хитрость заключается в использовании inputname следующим образом:

function runCode(varargin)
for ii = 1:nargin
   switch inputname(ii)
      case 'var1', var1 = varargin{ii};
      case 'var2', var2 = varargin{ii};
      case 'var3', var3 = varargin{ii};
      case 'var4', var4 = varargin{ii};
      otherwise,   error('Illegal input argument')
   end
end

Остальной функцией будет тело сценария OP, которое содержит следующий код:

if exist('var1','var')
   % ...
end

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

0 голосов
/ 05 сентября 2018

Спасибо за все отзывы. Так как функция, которую я хочу вызвать, иногда вызывается из одного и того же места, но с разными переменными, я не могу изменить способ настройки параметров. Итак, то, что я сделал, может заставить вас плакать, но у меня есть сценарий установки, который я вызываю перед функцией, которая проверяет, существуют ли параметры или нет, и устанавливаю их в NaN, если их нет. Это то же самое решение, которое я имел раньше, но в сценарии.

PS Я согласен, что это нужно оставить скриптом, но они действительно хотят, чтобы это была функция ¯_ (ツ) _ / ¯

0 голосов
/ 01 сентября 2018

Вы можете сделать входные данные парными аргументами, поэтому вы называете это следующим образом:

runCode ( 'var1', 123, 'var2', 456, 'var4', 789)

Где ваша функция

function runCode ( varargin )
  defaults.var1 =[];
  defaults.var2 =[];
  defaults.var3 =[];
  defaults.var4 =[];

  for ii = 1:2:nargin
    if isfield ( defaults, varargin{ii} )
      defaults.(varargin{ii}) = varargin{ii+1};
    else
      Throw error?
    end

Затем вы изменяете проверку на var3, чтобы проверить, является ли значение defaults.var3 пустым.

...