function varargout = myFunc(fid, varargin)
% ** a skeleton file of the suggested trick **
%
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Bothering situations when you code in Matlab:
%
% << Case 1 >>
%
% If you extensively use the Matlab, you'll soon find that your project
% folder become full of small m-files. You may organize them in folders
% or you may incorporate similar functionalities in an object using OOP.
% However, sometimes, you just write some functions in a single m-file,
% though functions other than the one at the top can be called only
% within the m-file. This is perfectly fine because you usually expect
% these functions never be used by other m-files.
%
% Then, later, you find yourself wanting to access those small functions
% from other m-files. Now, you need to refactor those as individual
% m-files.
%
% That's pain. You just want to use it as it is. You don't want to make
% another m-file for that tiny function. Making a lot of such small
% m-files turns the folder mess like a big toy box. It becomes more and
% more difficult to find the one you want. You even just forget what you
% have.
%
% There are ways to avoid this pain (such as OOP as I already mentioned).
% But they want to suck your attention, planning, designing and so on and
% so forth. You want a real quick simple fix for it.
%
%
% << Case 2 >>
%
% You have an m-file that includes a few subfunctions. Initially, it
% was not a big deal. But as your project progress, the subfunction
% itself became pretty long. Then you found something wrong with it. You
% want to debug it. You mark some break points and run the top level
% function of the m-file. You step into the subfunction of trouble.
% You think you found something, modify a little bit, and save it, ...
% which makes you get out of the current context. You need to run the
% whole function from the start all again to get to that point. You don't
% want to run all of the main function again just to run that sub-
% function. It takes too much time and is cumbersome. You want to run it
% with a simple parameter right from the command window.
%
% Again, you decide to refactor the subfunction out of the m-file.
% Afterall, it became too big to co-exist with the main function in a
% single m-file. But then, it is not the only subfunction that you
% need to refactor. There are lots of them. Your project folder ends up
% like a trash can.
%
%
% << Case 3 >>
%
% You want to have an m-file that has several functionalities using a
% token. For example, if the token is 'A', the function do something. If
% the token is 'B', the function do something else. The problem is that
% 'A' and 'B' requires different number of inputs/outputs. Worse, those
% inputs/outputs have very different meaning. Even worse, each of 'A' and
% 'B' needs pretty long codes.
%
% Natual solution for this case is to use something like 'switch'.
% 'switch' is a very simple good solution. But, because the meaning of
% inputs/outputs are different, the code reads very confusing. If each of
% 'A' and 'B' requires long codes, then it is hard to find out where you
% are in the 'switch' statement.
%
% Again, refactoring each case as an individual m-file could be a good
% solution. But, sometimes (not often though), you need to use the same
% function name.
%
%
%
% Solution: << My suggestion as a quick-fix >>
%
% Let's say the name of your m-file is 'myFunc', and there are several
% other subfunctions (mySub_A, mySub_B, etc) in the same m-file. Now you
% want to access "mySub_A" from outside. Then do the following two steps.
%
% 1. Rename your top function (myFunc) to something else, such as
% 'main' or 'myFunc_original', or whatever you want (I'll use
% 'main').
%
% 2. Add the following function at the top of your m-file.
%
% function varargout = myFunc(fid, varargin)
% if ~exist('fid','var')
% % add your default action for this m-file. Like...
% help myFunc
% disp('It needs a function name to call.');
% return;
% end
% fh = str2func(fid);
% [varargout{1:nargout}] = fh(varargin{:});
%
% Note that the function name should match the m-file name, which is
% 'myFunc' in this case.
%
%
% Caution: There is one problem to this approach. You have to update all
% calls to the original myFunc like following.
%
% From
% [out1, out2, ...] = myFunc(param1, param2, ...)
% To
% [out1, out2, ...] = myFunc('main', param1, param2, ...)
%
% Now you can call any of your other functions in this m-file by running
%
% myFunc('mySub_A', a, b);
% [e, f] = myFunc('mySub_B', c, d);
%
% and so on. Inspect this skeleton file for more detail. (Read comments
% carefully.
%
% << END >>
%
%
% Afterwords:
%
% I apply this trick whenever I begin writing a new m-file, because, with
% virtually no exception, I write at least a few functions in a single
% m-file. Writing just one function per one m-file makes the project
% folder mess like hell. Using OOP is an elegant way, but sometimes, it
% is simply unnecessary complexity for the job. With this trick, my
% project folder is filled with a few m-files with highly descriptive
% (functionally-grouped) name. I can even version/debug utility functions
% easily. Furthermore, different m-files can use the same utility
% function names, because each subfunction is unreachable from other
% m-files. So, different version of project can use the same name for
% slightly different versions of utility functions. One caveat is this:
% If you change the file name of the m-file, you need to fix all
% instances calling the functions of that m-file. So, create a very good
% name for your m-file so that you shouldn't change it later.
%
% Anyway, I hope you like this trick too.
%
% (cf)
% If you ever need a big data structure that needs to be manipulated
% by several functions, go for OOP. That is the right way. The proposed
% trick is by no means meant to be an alternative/replacement of OOP,
% though it resembles a very small portion of OOP, called
% "static methods". Fortunately, it does not come without advantage.
% There is convenience of no need to declare anything in the class
% definition. You can add whatever subfunctions in the m-file and
% they become accessible from outside right away.
%
%
% Acknowledgement: 'us' for discussion during the initial development of
% this idea a few years ago.
%
%
% See also:
% <a href="web([docroot '/techdoc/matlab_prog/f4-70666.html'])">subfunctions</a>
% <a href="matlab: web([docroot '/techdoc/matlab_oop/brdqiu3.html'])">Static methods</a>
% <a href="matlab: doc function_handle">function_handle</a>
% <a href="matlab: doc str2func">str2func</a>
% <a href="matlab: doc varargin">varargin</a>
% <a href="matlab: doc varargout">varargout</a>
%
% << Default action >>
% Change this part as you wish.
% If you don't want any default action, just remove this portion.
if ~exist('fid','var')
help myFunc
disp('Showing help is the default action of myFunc.');
disp('Use a function name as the first argument.');
return;
end
% If a function name is given, use it to call subfunction.
fh = str2func(fid);
[varargout{1:nargout}] = fh(varargin{:});
function [e,f]=main(a,b,c,d) % This was the original myFunc
mySub_A(a,b);
[e,f]=mySub_B(c,d);
% Of course, you may call the same functions like the following and get the
% same result even within the same m-file ~! This is very handy when you
% want to debug subfunctions.
myFunc('mySub_A',a,b);
[e,f]=myFunc('mySub_B', c,d);
function mySub_A(a,b)
disp(a);
disp(b);
function [a,b]=mySub_B(c,d)
a=c+d;
b=c-d;
% This idea works just as well for varargin/out functions.
function varargout=mySub_C(k,l)
for i=1:nargout
k=k+l;
varargout{i}=k;
end
function varargout=mySub_D(varargin)
varargout(1:nargout)={[]};
n=min(nargout,nargin);
[varargout{1:n}]=deal(varargin{1:n});