Mercurial > hg > ishara
view general/funutils/@func/func.m @ 61:eff6bddf82e3 tip
Finally implemented perceptual brightness thing.
author | samer |
---|---|
date | Sun, 11 Oct 2015 10:20:42 +0100 |
parents | e44f49929e56 |
children |
line wrap: on
line source
classdef func properties (GetAccess=private, SetAccess=private) fn args slots end methods % A func is a partially applied function: Any given function can % have some arguments bound to some given parameters, producing a % new function which needs only the remaining unbound parameters to % be supplied. In addition, the order in which parameters supplied % in a subsequent invocation are bound to unbound arguments can be % controlled using a slot permutation mechanism. Subscripting operation % () is overloaded so that function application works in the normal % way except when there are no arguments, in which case you must use FEVAL. % % For example, if linspace is a function such that % % linspace(a,b,n) % % returns an array of n values linearly spaced between a and b, % then after % % fromzero=func(@linspace,0) % % fromzero(b,n) returns n linearly spaced values from 0 to b. % The arguments can be permuted, eg, % % perm(func(@linspace),[3 1 2]) % % returns a function that takes the arguments in the order (n,a,b) % instead of (a,b,n). Permutation and binding can be combined, eg % % countdown=bind(perm(func(@linspace),[3 2 1]),10) % countdown(5,50) % ans= % 50 45 40 35 30 25 20 15 10 5 % % See Also: % PERM, BIND, CURRY, FEVAL, BINDAT % % Internal structure: % cfn.fn : an ordinary matlab function handle % cfn.args : a cell array with bound arguments filled in in the order % that the ordinary function fn expects them. There may be % empty slots if the arguments have been permuted (see CFPERM) % cfn.slots : List of empty slots in the order that they are intended to be % bound when this curried function is evaluated or has more % parameters bound. Eg, the first parameter will be bound to % to the slots(1)'th argument of the eventual call to cfn.fn % default function is null function function c=func(fn,varargin) if nargin<1, fn=@nop; end if isa(fn,'func'), c=fn; elseif isa(fn,'struct'), c.fn=fn.fn; c.args=fn.args; c.slots=fn.slots; else c.fn=fn; c.args=varargin; c.slots=[]; end end % bind - Bind arguments to a func to create partially applied function % % bind(fn,a1,a2,..) % fn is curried function returned by FUNC, BIND or PERM, % the given parameters are bound to the free slots of the function % and a new curried function is returned. % Matlab 'feature': if ANY of the paremeters % to bind are function objects, then this function gets called, even % if the first parameter is just an ordinary function pointer. function c=bind(c,varargin) if isa(c,'function_handle'), c=func(c); end % first, fill available slots in arg list using supplied args m=min(length(c.slots),length(varargin)); c.args(c.slots(1:m))=varargin(1:m); c.slots=c.slots(m+1:end); % remove filled slots c.args=horzcat(c.args,varargin(m+1:end)); % append any left over args end % BINDAT: Bind arguments at specified positions to create partially applied % function % % BIND(cfn,pos,a1,a2,..) % If cfn is an ordinary function, the parameters a1, a2 etc % are bound at the positions specified in pos(1),pos(2), etc. % Otherwise, the same as BIND. % % See BIND % need to make sure pos is a complete permutation before % calling perm function c=bindat(c,pos,varargin) pos=[pos setdiff(1:max(pos),pos)]; c=bind(perm(c,pos),varargin{:}); end % DISPLAY - Display FUNC object as string function display(c), disp([tostring(c),sprintf(' :: func(%d->%d)',nargin(c),nargout(c))]); end % FEVAL: Evaluate partially applied function % % FEVAL(cfn,a1,a2,...) % The given parameters a1, a2, etc. are bound to the arguments of cfn, % and eventually to the arguments of a matlab function, possibly % permuted according to cfn.slots (see CFPERM) function varargout=feval(c,varargin) % first, fill available slots in arg list using supplied args if ~isa(c,'func'), [varargout{1:max(1,nargout)}] = builtin('feval',c,varargin{:}); return; % error('This shouldn''t be happening!'); end m=min(length(c.slots),length(varargin)); args=c.args; args(c.slots(1:m))=varargin(1:m); % append any left over args if nargout==0, c.fn(args{:},varargin{m+1:end}); else [varargout{1:max(1,nargout)}] = c.fn(args{:},varargin{m+1:end}); end end % GETARG - Extract a bound argument from a FUNC object % getarg :: (func (D1,...,Dn)->R, k:natural) -> Dk function a=getarg(c,n), a=c.args{n}; end % GETFN - Get ordinary function handle from FUNC object function fn=getfn(c), fn=c.fn; end % PERM: permute arguments to a curried function % PERM(cfn,perm) % cfn can be an ordinary function handle or a curried function as returned % by BIND or PERM. % % The 1st argument of PERM(F,P) will bind to the P(1)'th argument of F. % Sequential permutations compose properly. % P must be a complete permutation: if length(P)=L, then P must % contain each of the intergers 1 to P exactly once. % The binding order of arguments after the Lth is not affected. function c=perm(c,slots) m=length(c.slots); n=length(slots); l=length(c.args); if m<n, c.slots=[c.slots l+1:l+n-m]; elseif m>n, slots=[slots n+1:m]; end c.slots=c.slots(slots); end function varargout=subsref(c,S) % SUBSREF - Subscript referencing for FUNC objects % % f(a,b,c)=feval(f,a,b,c) - parenthesis subsref invokes the function % f{a,b,c}=bind(f,a,b,c) - braces subsref binds more arguments s=S(1); switch s.type case '()' % first, fill available slots in arg list using supplied args m=min(length(c.slots),length(s.subs)); args=c.args; args(c.slots(1:m))=s.subs(1:m); [varargout{1:nargout}] = c.fn(args{:},s.subs{m+1:end}); case '{}' varargout{1}=bind(c,s.subs{:}); if length(S)>1, [varargout{1:nargout}] = subsref(varargout{1},S(2:end)); end end end function str=tostring(c) % TOSTRING - Implementation of string conversion for FUNC objects % % tostring :: func -> string str=[]; slots=c.slots; m=length(slots); args=c.args; l=length(args); n=max(slots); if l<n, args=[args cell(1,n-l)]; l=n; end; for i=1:m args{slots(i)}=['#' num2str(i)]; end for i=1:l str=[str tostring(args{i}) ',']; end if n>0, str=[str ' ']; end if isa(c.fn,'function_handle') fstr=['@' func2str(c.fn)]; elseif isa(c.fn,'inline') fstr=['\' char(c.fn) '\']; end str=[ fstr '(' str '...)']; end function n=nargout(f), n=nargout(f.fn); end function n=nargin(f), n=nargin(f.fn)-length(f.args); end end end