function f = at(h,attrib)
% function f = at(h,attrib)
%
% Similar to f = @h but creates a function_handle with embedded attributes.
%
% h function_handle or name of function
% f function_handle
%
% Example: f = at('fminbnd');
% See also str2fun, @
%% Allow at('@cos'), at('cos'), at('cos.m'), at(@cos), even at('@cos.m')
if ischar(h) && h(1)=='@',
h = h(2:end);
end
if ischar(h) && length(h)>1 && strcmpi(h(end-1:end),'.m'),
h = h(1:end-2);
end
if ischar(h),
h = str2func(h);
end
if nargin<2,
attrib = funattrib(h);
end
f = funlabel(h,attrib);
function attrib = funattrib(h)
% function attrib = funattrib(h)
%
% h function_handle
% attrib cell array of key-value pairs describing function attributes
%
% Infer attributes of a function_handle
fmuse('/argument_passing_util','argin.m','argout.m');
secretCode = prod(double('fun')); % 1312740
attrib = {'-name',func2str(h),'-argin',argin(h),'-argout',argout(h),'-fun',secretCode,...
'-handle',h,'-attrib',{'-name','-argin','-argout','-fun','-attrib','-handle'}};
function f = funlabel(h,labels)
%function f = funlabel(h,labels)
%
% h function_handle
% labels cell array of key value pairs
% f function_handle
%
% Returns handle to a function f which is in every way identical to h
% unless an attribute is requested. For instance f('name')
%% Determine how many output arguments are required
[ignoreMe,locOut] = ismember('-argout',labels(1:2:end-1));
nArgOut = length(labels{2*locOut});
[ignoreMe,locIn] = ismember('-argin',labels(1:2:end-1));
nArgIn = length(labels{2*locIn});
%% Wrap
f = @(varargin) funeval(h,labels,nArgIn,nArgOut,varargin{:});
function [y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12] = funeval(h,labels,nArgIn,nArgOut,varargin)
%
% h function_handle
% labels cell array of key-value pairs
% varargin parameters to be passed to f
%
% Similar to feval except when an attribute is requested
%% Short-circuit and return an attribute?
if length(varargin)==1 && ischar(varargin{1}) && varargin{1}(1)=='-',
m = length(labels);
for k=1:2:m-1,
key = labels{k};
if strcmpi(key,varargin{1}),
y1 = labels{k+1};
return;
end
end
end
%% ... or just evaluate
% A little ugly
if length(varargin)<=nArgIn,
switch nArgOut
case 0, ;
case 1, y1 = feval(h,varargin{:});
case 2, [y1,y2] = feval(h,varargin{:});
case 3, [y1,y2,y3] = feval(h,varargin{:});
case 4, [y1,y2,y3,y4] = feval(h,varargin{:});
case 5, [y1,y2,y3,y4,y5] = feval(h,varargin{:});
case 6, [y1,y2,y3,y4,y5,y6] = feval(h,varargin{:});
case 7, [y1,y2,y3,y4,y5,y6,y7] = feval(h,varargin{:});
case 8, [y1,y2,y3,y4,y5,y6,y7,y8] = feval(h,varargin{:});
case 9, [y1,y2,y3,y4,y5,y6,y7,y8,y9] = feval(h,varargin{:});
case 10, [y1,y2,y3,y4,y5,y6,y7,y8,y9,y10] = feval(h,varargin{:});
case 11, [y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11] = feval(h,varargin{:});
case 12, [y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12] = feval(h,varargin{:});
otherwise
error('Current implementation of funeval supports at most twelve output arguments');
end
else
error(['funeval:supplied too many input arguments.']);
end