有时在 MATLAB 中将函数用作各种“常量”变量会很方便。但是最近我在使用这个功能的时候遇到了一个意想不到的错误。当我运行下面的 MWE 时,我收到错误 Undefined function or variable 'a'.
尽管该函数在同一文件中明确可用。当我注释掉 if
语句时,错误消失了。这似乎暗示 MATLAB 将 a
预解释为变量,即使从未到达变量赋值行,而忽略了存在同名函数的事实。这是一个 MATLAB 错误还是某种程度上的预期行为?
这是 MWE:
function matlabBugTest( )
if false
a = 'foo';
end
a
end
function b = a()
b = 'bar';
end
跟进:
我知道故意为一个变量和一个函数使用相同的名称似乎很奇怪,所以我将举一个例子来说明这在什么地方有用。例如,您可能希望使用一个函数来存储一些常量(如文件路径),但也希望能够使用不同的值以防找不到该函数。这种情况可能看起来像:
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
我知道语言设计决策通常是困难和复杂的,但是 MATLAB 在这里选择忽略同名函数的更不幸的后果之一是它破坏了函数和脚本/命令行之间的兼容性。例如,以下脚本在脚本中运行没有问题:
if false
a = 'foo';
end
a
其中函数 a
(如上所示)保存在它自己的文件中。
最佳答案
这与 Matlab 在编译时如何执行名称绑定(bind)有关。因为matlabBugTest
有一行给a
赋值,所以a
被确定为一个变量,后面那行a
是对该变量的引用,而不是对本地函数的调用。更多现代版本的 Matlab,例如我安装的 R2015a,会提供更清晰的错误消息:
At compilation, "a" was determined to be a variable and this variable is uninitialized. "a" is also a function name and previous versions of MATLAB would have called the function. However, MATLAB 7 forbids the use of the same name in the same context as both a function and a variable.
与其说它是一个错误,不如说它是由给定默认解析方法的命名方案引入的歧义,如果您以前从未遇到过该问题并且 m-lint 没有标记它,这可能会很烦人。 variables are poofed into the workspace 时会发生类似的行为无需事先初始化。
因此解决方案是将函数的名称或变量更改为不同的名称,我认为这无论如何都是很好的做法。
在考虑您的后续示例时,我注意到在函数中四处移动的一些有趣行为。首先,如果该函数是外部函数或嵌套函数,您会很好地讨论行为 by Suever's answer .但是,如果该函数是本地函数,您可以通过在将函数转换为变量之前调用该函数来绕过限制(至少在我的 R2014b 和 R2015a 安装中可以),只要您将其初始化或显式将其转换为变量在某一点。通过这些案例,matlabBugTest
的以下主体如此执行:
失败:
a if false a = 'foo'; end a
运行:
a if true a = 'foo'; end a
运行:
a = a; if false % runs with true as well. a = 'foo'; end a
我不完全确定为什么会出现这种行为,但显然解析器会根据函数的范围、符号出现的顺序以及在什么上下文中的不同来处理不同的事情。
所以假设这种行为没有也不会改变你可以尝试这样的事情:
pathConstant = pathConstant;
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
不过,这里完全是个人意见,我会做类似的事情
pathConstant = getPathConstant();
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
关于打破“函数和脚本/命令行之间的兼容性”,我真的不认为这是一个问题,因为当涉及到 Matlab 时,这是两个完全不同的上下文。您不能在命令行或脚本文件中定义命名函数;因此,Matlab JIT 没有任何负担来正确和明确地确定一个符号是函数调用还是变量,因为每一行都是按顺序执行的并且没有被编译(除了某些代码块之外,JIT 被设计为识别和优化像在脚本中循环)。现在至于为什么上面的声明杂耍有效,我不完全确定,因为它依赖于我一无所知的 Matlab JIT(我也没有上过编译器类(class),所以如果我想要)。
关于MATLAB 错误? "Undefined function or variable"函数和变量使用相同名称时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37472554/