如果函数也是MATLAB中的变量会发生什么?

Kan*_*hao 2 variables matlab namespaces keyword

标题可能听起来很奇怪.所以这是一个例子.

Say length是在MATLAB中广泛使用的关键字或内部函数,有人保存了一个名为的变量length.

我可以运行以下脚本而没有任何问题,但是如果我将它放在一个函数中它会产生错误(使用R2015b)

一个有效的脚本

clear length;
length = [1 2 4];
la = length;
clear length;
b = length(la);
Run Code Online (Sandbox Code Playgroud)

功能不起作用

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
Run Code Online (Sandbox Code Playgroud)

错误:引用已清除的变量长度.

为什么会这样?MATLAB如何以不同方式处理这些情况?这应该发生在其他功能/关键字上吗?

Sue*_*ver 10

问题

根据本答案中提供的描述,MATLAB实际解析函数并实际执行函数之前确定函数的范围.因此,它想知道(在运行函数之前)您是否打算将其length用作函数或变量.在您的情况下,它会看到您将其用作变量,因此即使清除变量也不能将其用作函数.

示威

  1. 实际上,如果我们执行以下操作,MATLAB将无法调用我们的函数:

    function test()
        %// Use length the function
        L = length([1,2,3]);
    
        %// Now use length as a variable
        length = 2;
    end
    
    Run Code Online (Sandbox Code Playgroud)

    错误:文件:test.m行:6列:6
    "长度"以前似乎用作函数或命令,与此处使用的变量名称相冲突.
    导致此错误的可能原因是您忘记初始化变量,或者您已使用load或eval隐式初始化它.

  2. 现在,如果我们更改我们的函数以便我们首先调用length函数,然后加载我们的文件并尝试访问该变量 length(已隐式初始化load)

    function test()
        %// Use the function length
        L = length([1,2,3]);
    
        %// Load the variable length
        load('data.mat') 
        la = length;
    end
    
    Run Code Online (Sandbox Code Playgroud)

    使用length时出错
    没有足够的输入参数.

    因为MATLAB事先确定了函数的范围,所以它只看到了函数 length,这样就可以防止length在函数后期用作变量,即使你试图从文件中加载它也是如此.这样,当您尝试访问该变量时, length其行为就像您在没有输入的情况下调用该函数一样 length.

    我们没有从#1看到相同错误的原因是因为MATLAB无法知道data.mat包含一个名为的变量,length并且无法提醒您这种意外行为.

  3. 现在您注意到,使用eval实际上允许您访问变量.为什么会这样,我不完全确定,但是eval当你调用它并且不受父函数的范围规则约束时,可能会确定范围.

    似乎eval试图确定是否length在运行时使用函数或变量版本,因为我们可以从同一函数中确认它们.

    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
    
    Run Code Online (Sandbox Code Playgroud)

摘要

所以这实际意味着,如果你定义一个length在你的函数中命名的变量,MATLAB将运行你的函数之前确定它,防止你在同length一个函数中使用它作为一个函数.使用脚本或在命令窗口时不会出现此问题,因为范围是在运行时计算的,length可以同时用作变量和函数(假设您clear length在调用函数之前调用length).

解决方案

最佳做法是始终 指定输出load.然后,数据作为一个struct而不是用当前工作空间来加载,文件中存储了所有变量.然后,它并不重要什么用户命名的一个变量,它是保证不与任何您的变量或MATLAB的内置功能的冲突,你能避免意外行为.

data = load('data.mat');
la = data.length;
Run Code Online (Sandbox Code Playgroud)

这也确保了MATLAB能够正确地确定函数的范围,因为它可以看到你有一个名为的变量,data并且所有内容都data.mat将被加载到这个变量中.

如果你必须

如果你想保持它们的方式,但length在加载文件后仍然可以访问内置函数(不指定输出参数).您可以使用builtin访问实际 length功能.

b = builtin('length', la);
Run Code Online (Sandbox Code Playgroud)