This works (plots an "empty" figure):
function testme
plot(1)
This works (returns 1):
function testme
plot = @(x)x;
plot(1)
This does not (Error: "Undefined function or variable 'plot'."):
function testme
if 0
plot = @(x)x;
end
plot(1)
What's going on here? Why does rewriting but not redefining an already defined function render the function undefined?
Note 1: this is not specific for builtin functions; the following code returns the same error:
function testme
if 0
myfun = @(x)x;
end
myfun(1)
function x=myfun(x)
x=x*2;
Note 2: the error occurs in a function environment, not in a script; the following code does not return an error (and plots the same empty figure as in the first example):
if 0
plot = @(x)x;
end
plot(1)
Update: For the interested reader, here is some background information on my original problem. The above examples are just minimum working samples to illustrate the main issue (which indeed feature dead end if statements). In practice, I was trying to make a function useable for colleagues who did not have certain library/toolbox functions available, by overwriting those functions for simplified custom ones if they did not exist, as a quick fix. In particular, it concerned imdilate (and imerode). The function looked something like the following:
function [myoutputs] = myfunction(myinputs) % if the images toolbox is not available, use the following simplified % replacement function if ~exist('imdilate','file') imdilate = @(IM,SE)vecdilate(IM,SE); end %% The original function goes here, which uses a lot of imdilate(IM,SE). %% local functions function M = vecdilate(IM,SE) % simplified version of imdilate (can only process 1-D vertical arrays) nSE = size(SE); nIM = size(IM); SE = logical(SE); % make logical if it isn't yet % copy and shift xth column x down. new border entries are 0: M = repmat([IM;zeros(nSE)],nSE); M = M(1:end-nSE(1)); M = reshape(M,[size(M,1)/nSE(1) nSE(1)]); % shrink back to column by taking max of every row: M = max(M(:,SE),[],2); M = M(ceil(nSE(1)/2)-1+(1:nIM(1))); % clip to obtain correct size
You might see that the replacement function covers some functionality of imdilate, but not all, and it might not be as efficient. The purpose simply was to use function A if it was available, and function B if it was not. To my surprise however, the former case returned an error, which eventually resulted in this question. For your interest, I solved the practical problem by renaming the function in the original code, and by using an if/else statement:
function [myoutputs] = myfunction(myinputs) % if the images toolbox is not available, use the following simplified % replacement function if ~exist('imdilate','file') mydilate = @(IM,SE)vecdilate(IM,SE); else mydilate = @(IM,SE)imdilate(IM,SE); end %% The original function goes here, which uses a lot of mydilate(IM,SE). %% local functions function M = vecdilate(IM,SE) etc. etc. etc.
Just-in-time-compilation (JIT) does not mean that there is no compilation and that every line is interpreted separately, so you can still mess with the code;)
The error would also appear if you use a not-defined function, where you woun't even expect the code to run, like
function [] = test()
if false
a = @(x)x;
end
a(1)
end
Scripts are stored command line entries, i.e. the compiler has no choice but to handle every line separately (you may want to think of it as a keyboard macro). Functions in contrast are encapsulated pieces of code. The compiler (in general) does not expect anything unknown + it thinks that this encapsulated piece of code might be reused. Therefore, it makes sure to do a proper job compile all code once beforehand (if the compile would do this all the time, it is called ahead-of-time compilation).
This becomes in particular obvious when your clear the variables in between:
function [] = test()
if false
plot = @(x)x;
else
clear all % clear vs clear all
end
plot(1)
end
(Note that clear
clears all variables but clear all
would also clear excising code (see MATLAB Execution Engine))
Have a look at this interesting blog post from Loren
MATLAB provides the best of both worlds by compiling MATLAB code on-the-fly, or just-in-time. MATLAB code is compiled whether it be in classes, functions, scripts, or simply at the command line. There is no explicit compile step for the user to initiate and MATLAB code can be executed in blocks as small as one line at a time. The MATLAB JIT compiler generates native machine level code that is optimized for the MATLAB code being executed and for the specific hardware platform.
Anyway, you should not write dead ends in your code or overwrite (native) functions. It is good to use function handles to overcome this problem, but make sure that you define it for all cases
function [] = test()
if false % dead end definition
fnc = @(x)x;
else
fnc = @plot;
end
fnc(1)
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With