#lua
Вопрос:
Внутри функции ( doloadstring
) я заметил, что loadstring
даже при передаче правильной строки переменная функции не изменяется. Что это дает?
Я предполагаю x
, что это локальная переменная и loadstring
имеет только глобальную область действия?`
print('this works as I expect')
x = 0
loadstring('x = 1')()
print(x)
print('this does not')
function doloadstring(x, s)
print(x)
loadstring(s)() -- loadstring does not appear to change a variable in a function, is it because x is local
print(x)
print(z)
end
doloadstring('0', 'x = 1') -- x is not changed
doloadstring('0', 'z = 1') -- z is created tho
Это и есть результат:
this works as I expect
1
this does not
0
0
nil
0
0
1
Ответ №1:
Да, результат заключается в том, что эта переменная x
не существует в среде, которую получает функция (эти две переменные никак не связаны). Существуют такие функции, как debug.upvaluejoin, debug.setupvalue и debug.setlocal, но ни одна из них не «соединит» локальную переменную с функцией upvalue, чтобы сделать их одинаковыми.
Вы можете сделать следующее: (1) Создание новой среды, (2) внести (значения) локальные переменные и upvalues, (3) вызывать функцию с этой среды (пропуск среды load
для Lua 5.2 или использовать setfenv в Lua 5.1), и тогда (4) примет любые изменения от окружения и назначить их в локальных переменных/upvalues (вы можете использовать прокси-таблицы, чтобы упростить обнаружение изменений).
Вы можете проверить функции restore_vars и capture_vars из Mobdebug, которые делают что-то подобное. Это решает проблему в наиболее общем виде (когда вы не имеете никакой информации о переменных, которые могут быть использованы в свой «заряженный» функция), так что если у вас есть информация об этом, вы, безусловно, можете упростить логику и пройти определенную среду, которая соответствует тому, что вам нужно (вам не нужно, чтобы захватить все upvalues и локальные переменные).
Комментарии:
1. Спасибо! Довольно банальное решение, которое я бы сделал, — это просто создать временную глобальную переменную в качестве заполнителя и сделать строку под x.
2. Да, это должно сработать. Вы также можете сделать глобальную таблицу доступной и передавать значения туда и обратно, используя поля в этой таблице.