Как работает область видимости в Matlab?

Я только что обнаружил (к моему удивлению), что вызываю следующую функцию

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

дает и ошибка Undefined function or variable "fprintf". Мой вывод заключается в том, что область переменных определяется до выполнения (в моем ограниченном понимании того, как работает интерпретация компьютерных языков и, в частности, Matlab). Кто может дать мне некоторую справочную информацию об этом?

редактировать

еще одна интересная вещь, которую я забыл упомянуть выше это

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

производит Reference to a cleared variable fprintf.

4 ответов


MATLAB анализирует функцию до ее запуска. Например, он ищет имена переменных, независимо от ветвления, которое активирует (или не активирует) эти переменные. То есть область действия не определяется во время выполнения.

добавление: я бы не рекомендовал делать это, но я видел много людей, делающих вещи с MATLAB, которые я бы не рекомендовал. Но... подумайте, что произойдет, если кто-то определит свою собственную функцию под названием "false". Синтаксический анализатор перед выполнением не удалось знайте, что произойдет, если эта функция будет вызвана.


кажется, что в первый раз, когда компилятор MATLAB JIT анализирует m-файл, он идентифицирует все переменные, объявленные в функции. Кажется, ему все равно, объявляется ли указанная переменная в недостижимом коде. Так ваш местный fprintf переменная немедленно скрывает встроенную функцию fprintf. Это означает, что в отношении этой функции нет встроенной функции с именем fprintf.

конечно, как только это произойдет, все ссылки в функция fprintf относится к локальной переменной, и поскольку переменная никогда не создается, попытка доступа к ней приводит к ошибкам.

очистка переменной просто очищает локальную переменную, если она существует, она не верните встроенную функцию в область видимости.

чтобы вызвать встроенную функцию явно, вы можете использовать builtin


интересная ситуация. Я сомневаюсь, что есть подробная информация о том, как интерпретатор MATLAB работает в отношении этого странного случая, но есть несколько вещей, которые следует отметить в документации...

на функция приоритет используется MATLAB сначала помещает переменные:

прежде чем предположить, что имя соответствует функции, MATLAB проверяет переменную с этим именем в текущем рабочее место.

конечно, в вашем примере переменная fprintf фактически не существует в рабочей области, так как эта ветвь условного оператора никогда не вводится. Однако в документации по именованию переменных говорится следующее:

избегайте создания переменных с тем же именем, что и функция (например,i, j, mode, char, size и path). Как правило, имена переменных имеют приоритет над именами функций. Если вы создадите переменная, использующая имя функции, иногда дает неожиданные результаты.

это должен быть один из тех" неожиданных результатов", особенно когда переменная фактически не создана. Вывод заключается в том, что в MATLAB должен быть какой-то механизм, который анализирует файл во время выполнения, чтобы определить, что возможно переменные могут существовать в заданной области, конечный результат которых-функции все еще могут быть затенены переменными, которые появляются в M-файл даже если они в конечном счете не появляются в рабочее место.


EDIT: еще больше озадачивает, что функции, как exist и which даже не знают о том, что функция представляется тенью. Добавление этих строк перед вызовом в fprintf:

exist('fprintf')
which('fprintf')

дает этот вывод до возникновения ошибки:

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

показывая, что они все еще смотрите встроенный fprintf.


они могут дать представление:

Это может дать вам некоторую информацию о том, что тень:

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