如果一个函数在 MATLAB 中也是一个变量会怎样?
What happens if a function is also a variable in MATLAB?
标题可能听起来很奇怪。所以这里是例子。
说length
是MATLAB中广泛使用的关键字或内部函数,有人保存了一个名为length
的变量。
我可以运行下面的脚本没有任何问题,但是如果我把它放在一个函数中它会产生错误(使用 R2015b)
有效的脚本
clear length;
length = [1 2 4];
la = length;
clear length;
b = length(la);
函数不起作用
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.
为什么会这样? MATLAB 如何以不同方式处理这些情况?这应该发生在其他 functions/keywords 身上吗?
问题
根据 in this answer 提供的描述,MATLAB 在 实际执行函数之前 实际解析函数并确定函数的范围。因此,它想知道(在 运行 函数之前)您是打算将 length
用作函数还是变量。在你的情况下,它发现你正在将它用作变量,因此你 不能 将它用作函数 即使 你清除了变量.
示威活动
所以实际上,如果我们执行以下操作,MATLAB 将根本无法调用我们的函数:
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.
现在,如果我们更改我们的函数,以便我们首先将 length
作为函数调用,然后加载我们的文件并尝试访问 变量 length
(用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.
因为 MATLAB 预先确定了函数的作用域,它只看到了 函数 length
这防止了 length
以后被用作变量在函数中,即使您尝试从文件加载它。这样,当您尝试访问 variable length
时,它的行为就好像您调用了 function length
一样没有输入。
我们没有看到与 #1 相同的错误的原因是因为 MATLAB 无法知道 data.mat
包含一个名为 length
的变量并且无法提醒您这个意外行为。
现在正如您所注意到的,使用 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
总结
所以这实际上意味着,如果您在函数中定义一个名为 length
的变量,MATLAB 将确定 先于 到 运行功能,防止您在同一功能中将 length
用作 功能 。使用脚本或使用命令 window 时不会出现此问题,因为范围是在运行时计算的,并且 length
可以用作变量和函数(假设您调用 clear length
在调用函数 length
).
之前
解决方案
最佳做法是始终 specify an output to load
。然后将数据作为 struct
加载,而不是用文件中存储的所有变量污染您当前的工作区。那么 什么 用户命名变量并不重要,它保证不会与您的任何变量或 MATLAB 的内置函数冲突,并且可以避免意外行为。
data = load('data.mat');
la = data.length;
这也确保 MATLAB 能够正确确定函数的范围,因为它可以看到您有一个名为 data
的变量,并且 data.mat
的所有内容都将加载到该变量中.
如果你必须
如果您想保持原样,但在加载文件后仍然可以访问内置 length
函数(不指定输出参数)。您可以使用 builtin
访问 real length
函数。
b = builtin('length', la);
标题可能听起来很奇怪。所以这里是例子。
说length
是MATLAB中广泛使用的关键字或内部函数,有人保存了一个名为length
的变量。
我可以运行下面的脚本没有任何问题,但是如果我把它放在一个函数中它会产生错误(使用 R2015b)
有效的脚本
clear length;
length = [1 2 4];
la = length;
clear length;
b = length(la);
函数不起作用
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.
为什么会这样? MATLAB 如何以不同方式处理这些情况?这应该发生在其他 functions/keywords 身上吗?
问题
根据 in this answer 提供的描述,MATLAB 在 实际执行函数之前 实际解析函数并确定函数的范围。因此,它想知道(在 运行 函数之前)您是打算将 length
用作函数还是变量。在你的情况下,它发现你正在将它用作变量,因此你 不能 将它用作函数 即使 你清除了变量.
示威活动
所以实际上,如果我们执行以下操作,MATLAB 将根本无法调用我们的函数:
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.现在,如果我们更改我们的函数,以便我们首先将
length
作为函数调用,然后加载我们的文件并尝试访问 变量length
(用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.因为 MATLAB 预先确定了函数的作用域,它只看到了 函数
length
这防止了length
以后被用作变量在函数中,即使您尝试从文件加载它。这样,当您尝试访问 variablelength
时,它的行为就好像您调用了 functionlength
一样没有输入。我们没有看到与 #1 相同的错误的原因是因为 MATLAB 无法知道
data.mat
包含一个名为length
的变量并且无法提醒您这个意外行为。现在正如您所注意到的,使用
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
总结
所以这实际上意味着,如果您在函数中定义一个名为 length
的变量,MATLAB 将确定 先于 到 运行功能,防止您在同一功能中将 length
用作 功能 。使用脚本或使用命令 window 时不会出现此问题,因为范围是在运行时计算的,并且 length
可以用作变量和函数(假设您调用 clear length
在调用函数 length
).
解决方案
最佳做法是始终 specify an output to load
。然后将数据作为 struct
加载,而不是用文件中存储的所有变量污染您当前的工作区。那么 什么 用户命名变量并不重要,它保证不会与您的任何变量或 MATLAB 的内置函数冲突,并且可以避免意外行为。
data = load('data.mat');
la = data.length;
这也确保 MATLAB 能够正确确定函数的范围,因为它可以看到您有一个名为 data
的变量,并且 data.mat
的所有内容都将加载到该变量中.
如果你必须
如果您想保持原样,但在加载文件后仍然可以访问内置 length
函数(不指定输出参数)。您可以使用 builtin
访问 real length
函数。
b = builtin('length', la);