function varargout = slinvoke(invoke_descr, varargin)
%SLINVOKE Invokes a function
%
% $ Syntax $
% - [y1, y2, ..., yn] = slinvoke(invoke_descr, x1, x2, ..., xm)
%
% $ Arguments $
% - invoke_descr: the invoking descriptor
% - x1, x2, ..., xm: the input arguments
% - y1, y2, ..., yn: the output arguments
%
% $ Description $
% - [y1, y2, ..., yn] = slinvoke(invoke_descr, placepos, x1, x2, ..., xm)
% invokes some function with a specified manner. The invoking descriptor
% can be in following form:
% 1. a string representing the function name, a function handle or an
% inline object. In this case, no fixed argument is binded. The x1,
% x2, ..., xm are directly fed to the function.
% 2. a cell array like {func, var_pos, fa1, fa2, ... fak}. Here
% func is the function name, function handle or inline object that
% is to be invoked. var_pos is the positions of variable arguments.
% fa1, fa2, ... are the fixed(binded) arguments. If var_pos is [],
% the variable arguments will be put first.
%
% $ Examples $
% - Invoke a function without fixed arguments
% \{
% slinvoke('plot', x, y);
% y = slinvoke({'sin', []}, x);
% \}
%
% - Invoke a function with fixed arguments binded, the following pairs
% of statements are equivalent.
% \{
% K = slinvoke({'strfind', 1, 'pattern'}, s);
% K = strfind(s, 'pattern');
%
% slinvoke({'plot', [1 2], 'r-'}, x, y);
% plot(x, y, 'r-');
%
% slinvoke({'plot', 2, x, 'b+'}, y);
% plot(x, y, 'b+');
%
% b = slinvoke({'isequal', [], 0}, x);
% b = isequal(x, 0);
% \}
%
% $ History $
% - Created by Dahua Lin on Dec 28th, 2005
%
%% parse input arguments
if ~iscell(invoke_descr)
func = invoke_descr;
var_pos =[];
fix_args = {};
else
len_invoke_descr = length(invoke_descr);
func = invoke_descr{1};
if len_invoke_descr >= 2
var_pos = invoke_descr{2};
else
var_pos = [];
end
if len_invoke_descr >= 3
fix_args = invoke_descr(3:end);
else
fix_args = {};
end
end
if isempty(var_pos) && ~isempty(varargin)
var_pos = 1:length(varargin);
end
n_fix_args = length(fix_args);
n_var_args = length(var_pos);
if length(varargin) ~= n_var_args
error('sltoolbox:argmismatch', ...
'The variable input arguments do not match that described in invoking descriptor');
end
%% organize input arguments
if n_fix_args == 0 && n_var_args == 0
if nargout == 0
feval(func);
else
[varargout{1:nargout}] = feval(func);
end
elseif n_var_args == 0
if nargout == 0
feval(func, fix_args{:});
else
[varargout{1:nargout}] = feval(func, fix_args{:});
end
else
n_args = max(n_fix_args + n_var_args, max(var_pos));
input_args = cell(1, n_args);
indicator_var = false(1, n_args);
indicator_var(var_pos) = true;
fix_pos = find(~indicator_var);
for i = 1 : n_var_args
input_args{var_pos(i)} = varargin{i};
end
for i = 1 : n_fix_args
input_args{fix_pos(i)} = fix_args{i};
end
if nargout == 0
feval(func, input_args{:});
else
[varargout{1:nargout}] = feval(func, input_args{:});
end
end