samer@27: % thunk(B@typelist(M)) ~ a thunk is something that eventually yields M outputs samer@4: classdef thunk samer@4: properties (GetAccess=private, SetAccess=immutable) samer@27: head % :: (A@typelist(N) -> B | thunk(B)) samer@27: args % :: A@typelist(N) samer@4: end samer@4: methods samer@4: % thunk - create delayed evaluation samer@4: function f=thunk(h,varargin), f.head=h; f.args=varargin; end samer@4: function s=tostring(f), s=sprintf('%s(%s)',tostring(f.head),commalist(map(@tostring,f.args))); end samer@4: function display(f), display([tostring(f),' :: thunk']); end samer@4: samer@4: % fforce - Completely force a thunk, if keep evaluating till not a thunk samer@4: function f=fforce(f), while isa(f,'thunk'), f=force(f); end; end samer@4: samer@4: function varargout=force(f), [varargout{1:nargout}] = feval(f.head,f.args{:}); end samer@4: samer@4: % SUBSREF - Subscript referencing for FUNC objects samer@4: function varargout=subsref(f,S) samer@4: s=S(1); samer@4: switch s.type samer@4: case '()', [varargout{1:nargout}] = feval(f.head,f.args{:}); samer@4: end samer@4: end samer@4: end samer@4: end samer@4: samer@4: function s=commalist(a) samer@4: if isempty(a), s=''; samer@4: elseif length(a)==1, s=a{1}; samer@4: else s=[a{1},',',commalist(a(2:end))]; samer@4: end samer@4: end