Что означает в Lua назначение неопределенного идентификатора необъявленной переменной? - PullRequest
0 голосов
/ 16 октября 2010

Я просматривал файл кода Lua, и самый верх файла содержит:

    1  | TradeSkillFrameReset = TradeSkillFrame_LoadUI;
    2  | 
    3  | TradeSkillFrame_LoadUI = function()
    4  |    TradeSkillFrameReset();
            ...
    112|    TradeSkillFrame_LoadUI = TradeSkillFrameReset;
            ...
    114| end;

Самая первая строка, где они выполняют задание:

TradeSkillFrameReset = TradeSkillFrame_LoadUI;

На этом этапе в файле кода они присваивают необъявленный идентификатор (TradeSkillFrame_LoadUI) необъявленной переменной (TradeSkillFrameReset). Это разрешено в Lua?

  • является ли объявление переменной неявным?
  • все ли необъявленные идентификаторы считаются прямыми декларациями?

Еще более запутанным является то, что первый TradeSkillFrame_LoadUI, кажется, делает сам вызов:

TradeSkillFrame_LoadUI = function()
   TradeSkillFrameReset();

Как это не бесконечный цикл?


Редактировать: Добавлены оставшиеся ссылки на TradeSkillFrameReset и TradeSkillFrame_LoadUI.

Ответы [ 5 ]

5 голосов
/ 16 октября 2010

Если TradeSkillFrame_LoadUI - глобальная функция, первый оператор захватывает эту функцию в TradeSkillFrameReset.

. Присвоение TradeSkillFrame_LoadUI затем заменяет глобальную функцию новой, которая сначала вызываетисходная функция через ссылку TradeSkillFrameReset.

Этот шаблон называется «перехват функций», здесь - это дополнительная информация об общей технике и некоторые подробности, касающиеся среды World of Warcraft Lua (гдеэтот скрипт может происходить, в соответствии с именем функции)

Некоторый пример кода, чтобы прояснить это:

function SomeGlobalFunction()
    print("I'm the original global function")
end

OrigFunction = SomeGlobalFunction

SomeGlobalFunction = function()
    OrigFunction()
    print("And here's the modfied one...")
end

--...
SomeGlobalFunction()

это выведет следующий вывод:

Я оригинальная глобальная функция

А вот модифицированная ...

В качестве примечания, Луа зовут не все с большой буквы .

0 голосов
/ 17 октября 2010

Главное, что нужно убрать, это то, что для кода Lua легко внедрить глобальные переменные в другой код Lua. Я использовал Lua, где они используют среду для добавления глобальных переменных. Тот факт, что var не определен в этом файле, не означает, что он не существует. Его даже не нужно определять как глобальную переменную в другом файле, потому что вы можете программно внедрить его в таблицу окружения, как если бы это была любая другая таблица.

0 голосов
/ 16 октября 2010

Я бы предположил, что он делает что-то похожее на подъем функции Javascript, о котором вы можете прочитать здесь: Ссылка на значение JavaScript перед его объявлением - кто-то может объяснить это

0 голосов
/ 16 октября 2010

Если поведение глобальных переменных не было изменено в используемой вами среде, оператор абсолютно ничего не делает.

local TradeSkillFrameReset = TradeSkillFrame_LoadUI

Будет иметь эффект, создавая слот локальной переменной ""и делая код после этой точки, используйте слот локальной переменной для TradeSkillFrameReset вместо поиска глобальной переменной для него.Однако, как и в опубликованном вами коде, он просто присваивает глобальной переменной значение nil, что приводит к его стиранию, другими словами, не имеет значения, если оно уже было равно nil.

Причины могут бытьthere:

1) Среда, в которой выполняется код, делает что-то особенное, когда выполняется глобальное присвоение переменной, а не поведение по умолчанию простого присваивания.Я не думаю, что это вероятно, хотя, как если бы было какое-то особое поведение, поиск nil TradeSkillFrame_LoadUI, вероятно, вызвал бы ошибку.

2) Наиболее вероятная причина - просто для читабельности.Это позволит вам знать, что TradeSkillFrameReset будет правильно назначен для последующего захоронения где-то в коде, где вы не заметите это так легко.

0 голосов
/ 16 октября 2010

В первой строке, поскольку TradeSkillFrame_LoadUI - неинициализированная переменная, тогда эта первая строка:

TradeSkillFrameReset = TradeSkillFrame_LoadUI;

То же, что и изготовление:

TradeSkillFrameReset = nil

Функция ниже, которая не входит в бесконечный цикл, потому что TradeSkillFrameReset на самом деле не «указывает ни на что».

Я предполагаю, что позже в коде он будет правильно инициализирован. Вот так:

TradeSkillFrameReset = TradeSkillFrame_LoadUI;

TradeSkillFrame_LoadUI = function()  -- 1. function declaration
   TradeSkillFrameReset();

   [...snip...]
end;

[... snip ...]
TradeSkillFrameReset = somethingElse -- 2. initialized to something else
TradeSkillFrame_LoadUI()             -- 3. function invocation

Хитрость в том, что вы можете определить функцию для 1 и использовать значение переменной для 3, в то же время изменив ее на 2.

Дайте мне знать, если это недостаточно ясно.

...