What happens if a function is also a variable in M

2019-01-15 21:37发布

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?

1条回答
2楼-- · 2019-01-15 22:02

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

  1. 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.

  2. 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.

  3. 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);
查看更多
登录 后发表回答