Я согласен, что это несколько неинтуитивно, что это не работает.
Вы хотите сказать, что в любой точке кода существует явный набор переменных, которые являются «видимыми» - некоторые могут быть локальными, некоторые могут быть глобальными, но есть некоторая карта, которую может интерпретировать интерпретатор используйте для разрешения имен любого типа.
Когда вы загружаете кусок с использованием файла dofile, он может видеть, какие существуют глобальные переменные в настоящее время, но, по-видимому, он не видит никаких локальных переменных. Мы знаем, что «dofile» не похож на макросы включения C/C++, что даст точно то поведение, которое вы описываете для локальных переменных, но все же вы можете разумно ожидать, что эта его часть будет работать одинаково.
В конечном счете нет ответа, но «это не так, как они указали язык». Единственный , удовлетворяющий ответ, вероятно, по строкам ', потому что иначе это вызовет неочевидную проблему X' или ', потому что тогда случай использования Y будет медленнее.
Я считаю, что лучшим ответом является то, что если все имена динамически восстанавливаются в соответствии с областью, в которой они загружаются при использовании loadfile/dofile, это будет препятствовать большой оптимизации и тому подобное при компиляции блоков в байт-код. В системе lua разрешение имен работает как «либо локально в этой области, а затем привязывается к этому (известному) объекту, или же это поиск в (уникальной) глобальной таблице». Эта система довольно проста, есть только несколько вариантов и не много места для сложности.
Я не думаю, что работающий байтовый код даже отслеживает имена локальных переменных, он отбрасывает их после компиляции куска. Они должны были бы отменить эту оптимизацию, если бы они хотели разрешить динамическое разрешение имен при загрузке блока, как вы предлагаете.
Если ваш вопрос не совсем почему но как я могу заставить его работать в любом случае, то один из способов вы можете сделать это, в главном сценарии, ставить какие-либо локальные переменные, которые вы хотите быть видимый в среде сценария, который вызывается. Когда вы это делаете, вам нужно разделить dofile на несколько вызовов. Это немного отличается в lua 5.1 vs lua 5.2.
В Lua 5.1:
В a.lua
:
local shared = { x = 5 }
temp = loadfile('b.lua')
setfenv(temp, shared)
f = temp()
f()
В Lua 5.2:
В a.lua
:
local shared = { x = 5 }
temp = loadfile('b.lua', 't', shared)
f = temp()
f()
Спасибо за ваш ответ! Еще одна вещь: если тело функции 'fun' слишком велико, что я не хочу помещать его в файл' a.lua', а отдельный файл (как то, что я делаю в первом случае, который doesn ' t work), есть ли какая-нибудь хорошая идиома, чтобы заставить ее работать? –