Как работает обзор в Matlab?

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

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

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

Edit

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

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

создает Reference to a cleared variable fprintf.

Ответ 1

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

ДОБАВЛЕНИЕ: Я бы не рекомендовал делать это, но я видел много людей, которые делали вещи с MATLAB, которые я бы не рекомендовал. Но... подумайте, что произойдет, если кто-то определит свою собственную функцию под названием "ложь". Предзадачный анализатор не мог знать, что произойдет, если эта функция была вызвана.

Ответ 2

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

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

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

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

builtin( 'fprintf', 'test' );

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

Ответ 3

Интересная ситуация. Я сомневаюсь, что есть подробная информация о том, как работает интерпретатор 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.