Matlab中的作用域是如何工作的?

Matlab中的作用域是如何工作的?,matlab,scope,Matlab,Scope,我刚刚发现(出乎意料地)调用以下函数 function foo() if false fprintf = 1; else % do nothing end fprintf('test') 给出和错误未定义的函数或变量“fprintf”。我的结论是,变量的范围是在运行前确定的(我对计算机语言的解释,特别是Matlab的工作原理了解有限)。有人能给我一些关于这方面的背景资料吗 编辑 另一件有趣的事我忘了在上面提到的是 function foo() if false fprintf

我刚刚发现(出乎意料地)调用以下函数

function foo()
if false
   fprintf = 1;
else
  % do nothing
end
fprintf('test')
给出和错误
未定义的函数或变量“fprintf”
。我的结论是,变量的范围是在运行前确定的(我对计算机语言的解释,特别是Matlab的工作原理了解有限)。有人能给我一些关于这方面的背景资料吗

编辑

另一件有趣的事我忘了在上面提到的是

function foo()
if false
   fprintf = 1;
else
  % do nothing
end
clear('fprintf')
fprintf('test')

生成对清除变量fprintf的
引用

有趣的情况。我怀疑是否有关于MATLAB解释器如何在这种奇怪的情况下工作的详细信息,但是在文档中有一些东西需要注意

MATLAB使用的方法首先放置变量:

在假设名称与函数匹配之前,MATLAB会在当前工作区中检查具有该名称的变量

当然,在您的示例中,变量
fprintf
实际上不存在于工作区中,因为从未输入条件语句的该分支。但是,有关变量命名的文档说明:

避免创建与函数同名的变量(例如
i
j
模式
字符
大小
,以及
路径
)。通常,变量名优先于函数名。如果创建使用函数名的变量,有时会得到意外的结果

这一定是“意外结果”之一,尤其是当变量没有实际创建时。结论是,MATLAB中必须有某种机制在运行时解析文件,以确定在给定范围内可能存在哪些变量,其最终结果是函数仍然会被出现在m文件中的变量遮挡,即使这些变量最终没有出现在工作区中


编辑:更令人困惑的是,函数类似于,甚至没有意识到函数似乎被隐藏的事实。在调用
fprintf
之前添加这些行:

exist('fprintf')
which('fprintf')
在错误发生之前提供此输出:

ans =
     5
built-in (C:\Program Files\MATLAB\R2012a\toolbox\matlab\iofun\fprintf)

表明他们仍然可以看到内置的
fprintf

似乎在MATLAB JIT编译器第一次解析m文件时,它识别了函数中声明的所有变量。它似乎并不关心所述变量是否在不可访问的代码中声明。因此,本地
fprintf
变量会立即隐藏内置函数
fprintf
。这意味着,就这个函数而言,没有名为
fprintf
的内置函数

当然,一旦发生这种情况,函数中对
fprintf
的每个引用都会引用局部变量,而且由于变量从未实际创建过,因此尝试访问它会导致错误

清除变量只会清除局部变量,如果它存在,则不会将内置函数带回作用域

要显式调用内置函数,可以使用该函数

builtin( 'fprintf', 'test' );

上面的一行将始终在MATLAB命令行中打印文本,而不考虑可能影响
fprintf
函数的局部变量。

MATLAB在函数运行之前解析函数。例如,它查找变量名,而不管激活(或不激活)这些变量的分支是什么。也就是说,范围不是在运行时确定的

builtin( 'fprintf', 'test' );

附录:我不建议这样做,但我见过很多人用MATLAB做我不推荐的事情。但是考虑一下如果有人定义他们自己的函数叫做“false”会发生什么。运行前解析器无法知道如果调用该函数会发生什么情况。

这些可能提供了一些见解:

这可以为您提供有关阴影内容的一些信息:

which -all
(以下被确认为错误) 其中一个问题是,工作区结构和路径上的类具有特定的作用域和类型优先级(如果您是我的话),这可能会让您大吃一惊

例如,在2017b:

% In C.m, saved in the current directory
classdef C
 properties (Constant)
   x = 100;
 end
end

% In Command window
C.x = 1;
C.x       % 100
 C.x      % 1 (Note the space)
C.x*C.x   % 1
disp(C.x) % 1

你什么时候打电话给fprintf?在
foo
之前或之后?我怀疑也是这样。这里还有一件有趣的事情值得观察。请参阅我的编辑。
存在
在运行时检查它们,它们不受JIT特性的影响。它们怎么可能?他们对调用工作区中的局部变量一无所知。甚至在像C这样的语言中也是这样:如果在函数中局部地隐藏一个全局变量,那么这个全局变量当然不会隐藏在从那里调用的另一个函数中。如果你问我的话,这并不令人费解。我不知道
内置的
,很有趣!谢谢,您还可以将fprintf作为函数重新引入:
fprintf=str2func('fprintf')
,它将覆盖MATLAB认为隐藏它的(不存在的)变量。@sebhofer:请注意,
builtin
仅适用于已编译的MATLAB函数,也就是说,当你
编辑它们时,它们只向你显示帮助而没有代码。我希望我们能找一个MathWorks的人参与进来。欢迎来到这个网站!起初,我认为范围将在运行时确定,所以不管是否重新定义了false。不管怎样,谢谢你把这件事弄清楚!这真的很奇怪
其中C
表示C是一个变量
C
用字段x:1表示
C=struct<代码>C.x
给出100。但是前面没有空格。你可能想向MathWorks提交一份bug报告。变量
C
应该是类
C
的阴影。很好的发现。我认为你不需要免责声明:这是一个答案。这是标题中问题的补充信息。