The title may sound strange. So here is the example.
Say length
is a keyword or internal function that is widely used in MATLAB and someone saved a variable called length
.
I can run the following script without any issues, but if I place it within a function it produces an error (using R2015b)
A script that works
clear length;
length = [1 2 4];
la = length;
clear length;
b = length(la);
Function that does not work
function test(a)
length = [1 2 4];
save('data.mat','length');
clear length;
load('data.mat');
% load
la = length;
clear length;
b = length(la);
end
error: Reference to a cleared variable length.
Why does this happen? How does MATLAB treat these situations differently? Should this happen to other functions/keywords?
The Issue
Based on the description provided in this answer, MATLAB actually parses the function and determines the scope of the function before it actually executes the function. As such, it wants to know (prior to running a function) whether you intend to use length
as a function or variable. In your case, it sees that you are using it as a variable, and therefore you cannot use it as a function even if you clear the variable.
Demonstrations
So actually, if we do the following MATLAB will fail to call our function at all:
function test()
%// Use length the function
L = length([1,2,3]);
%// Now use length as a variable
length = 2;
end
Error: File: test.m Line: 6 Column: 6
"length" previously appeared to be used as a function or command, conflicting with its use here as the
name of a variable.
A possible cause of this error is that you forgot to initialize the variable, or you have initialized
it implicitly using load or eval.
Now, if we change our function so that we first call length
as a function, then load our file and try to access the variable length
(which was initialized implicitly with load
)
function test()
%// Use the function length
L = length([1,2,3]);
%// Load the variable length
load('data.mat')
la = length;
end
Error using length
Not enough input arguments.
Because MATLAB determined the scope of the function beforehand, it only saw the function length
and this prevents length
from being used as a variable later in the function, even when you attempt to load it from the file. That way, when you tried to access the variable length
it behaves as if you had called the function length
with no inputs.
The reason we didn't see the same error from #1 is because MATLAB had no way of knowing that data.mat
contained a variable named length
and couldn't alert you of this unexpected behavior.
Now as you noticed, using eval
actually allows you to access the variable. Why this is, I'm not completely sure but it likely that the scope for eval
is determined when you call it and isn't subject to the scope rules of the parent function.
It appears that eval
tries to determine whether to use the function or variable version of length
at runtime as we can get it to acknowledge both from within the same function.
function test()
%// Use the function length
L = length([1,2,3]);
%// Load the variable length
load('data.mat')
%// Eval can actually access the VARIABLE length
eval('la = length;');
%// Eval can ALSO access the FUNCTION length
eval('L = length([1,2,3])');
end
Summary
So what this effectively means, is that if you define a variable named length
in your function, MATLAB will determine that prior to running your function, preventing you from ever using length
as a function within that same function. This issue does not appear when working with a script or at the command window because the scope is computed at runtime and length
can be used as both a variable and function (given that you call clear length
prior to calling the function length
).
The Solution
Best practice is to always specify an output to load
. Then the data is loaded in as a struct
rather than polluting your current workspace with all of the variables stored within the file. Then it doesn't matter what the user named a variable, it is guaranteed to not conflict with any of your variables or MATLAB's built-in functions and you can avoid unexpected behavior.
data = load('data.mat');
la = data.length;
This also ensures that MATLAB is able to properly determine the scope of your function since it can see that you have a variable named data
and all contents of data.mat
will be loaded into this variable.
If you must
If you want to keep things the way that they are but still have access to the built-in length
function after loading the file (without specifying an output argument). You can use builtin
to access the real length
function.
b = builtin('length', la);