MATLAB is great for prototyping. Certain things are done so well. Anonymous functions are not one of them. Anonymous functions (e.g., myquicktestfun = @(X,Y) X+Y;
can be declared in a script (or from command line) workspace (nice for rapid prototyping), but they must be one-liners. This is so dumb, and probably only explainable as a result of some legacy syntax design/parsing mistake. Often you can do some gymnastics to condense a bunch of lines into one. If you can't then you need to literally make a file with the name of your function (e.g., myquicktestfun.m
) or you have to move your and populate it with your lines. This is anti-thical to rapid prototyping. And not just for the obvious reason that it's cumbersome and tedious to open a bunch of temporary files. The issue I ran into today is that it make it difficult to debug.
Consider I'm prototyping the following test_script.m
:
A = 1;
B = 2;
myfun = @(X,Y) X+Y;
C = myfun(A,B);
Now, suppose I'd like to replace X+Y
with two lines [~,Z] = someotherfun(Y); X+Z
. Since Z
comes as the second output argument I can't easily smoosh this into a one-liner (this is an example; there are many other reasons why you might need/want multiple lines in a function... duh!). So I'm either forced to make a new file myfun.m
or to convert my test_script.m
into test_fun.m
and then I can declare myfun
as a multi-line function:
function test_fun
A = 1;
B = 2;
function res = myfun(X,Y)
[~,Z] = someotherfun(Y);
res = X+Z;
end
C = myfun(A,B);
end
Converting the script to a function might be the way to go if I have lots of anonymous functions that may need to be turned into real, multi-line functions and I don't want to manage a bunch of .m
files.
However, I've ruined the rapid prototyping nature of my script. When I was using test_script
, after execution or upon an error I'm reset to the command line workspace. This has an important difference with the (awkward) debugger state that I'd need to use if I want access to all the variables introduced in the code above. For example, if I add a breakpoint or the line keyboard
in the function above:
function test_fun
A = 1;
B = 2;
function res = myfun(X,Y)
[~,Z] = someotherfun(Y);
res = X+Z;
end
C = myfun(A,B);
keyboard
end
I'll have read access to variables A
, B
, and C
so I can print out their values or pass them to functions (e.g., visualization etc.). But I cannot introduce a new variable,
K>> err = A+B - C;
Attempt to add "err" to a static workspace.
See Variables in Nested and Anonymous Functions.`
Booo. This is just as frustrating as one-linear anonymous functions. I can access variables, call functions (which assign their own internal variables), but can't assign a variable. I'd be happy even with a temporary "debug workspace" (maybe this exists?).
To remedy this, I developed an absurd, very MATLABberish, workaround. If I add the following line to my script (or execute it within the debugger), then all local variables will be added to the command line's workspace:
cellfun(@(v) assignin('base',v,evalin('caller',v)),who);
So then from the command line I can issue:
>>> test_fun(); A A = 1 B A = 2
Note: I must include the obligatory concession that most languages handle anonymous functions correctly in this regard (Python, Ruby, C++11, etc.). AFAIK, MATLAB is the only language that screwed this up.