В теории языков программирования, нелокальная переменная — переменная, которая не определена в локальной области видимости. Хотя термин может относиться к глобальным переменным, он в первую очередь используется в контексте вложенных и анонимных функций, где некоторые переменные могут принадлежать как не локальной так и не глобальной области видимости.
В языке программирования Lua они называются upvalues.[1]
Примеры
Вложенные функции
В примере вложенной функции на языке программирования Python 3, который указан ниже, функция inner
определена в области видимости другой функции — outer
. Переменная x
локальна по отношению к функции outer
, но не локальна по отношению к функции inner
(и не глобальна в то же время):
def outer():
x = 1
def inner():
nonlocal x
x += 1
print(x)
return inner
В языке программирования JavaScript, местонахождение переменной определяется с помощью ближайшего выражения var
для этой переменной. В следующем примере, переменная x
локальна по отношению к функции outer
, так как она содержит выражение var x
, в то же время функция inner
нет. Таким образом x не локальна по отношению к функции inner
:
function outer() {
var x = 1;
function inner() {
x += 1;
console.log(x);
}
return inner;
}
Анонимные функции
В примере на языке Haskell, который следует далее в анонимной функции \x -> x + c
переменная c
нелокальная:
outer = let c = 1 in map (\x -> x + c) [1, 2, 3, 4, 5]
Проблемы с реализацией
Нелокальные переменные являются основной причиной сложности поддержки вложенных, анонимных, высшего порядка и тем самым первого класса функций в языках программирования.
Если вложенная функция или функции (взаимно) рекурсивны, то становиться сложно для компилятора знать точно, где в стеке вызовов была выделена память для нелокальной переменной, так как указатель кадра указывает только на саму локальную переменную вложенной функции и может существовать произвольное количество записей активации в стеке. Обычно эта проблема решается с использованием access links или display registers.
Если вложенная функция передается как аргумент в функцию высшего порядка замыкание, должно быть построено для нахождения нелокальных переменных. Если вложенная функция возвращается как результат из своей внешней функции (или хранится в переменной) нелокальные переменные не будут более доступны в стеке. Вместо этого они должны быть выделены в куче и время их жизни будет дольше времени жизни внешней функции, которая объявила и выделила их. В общих случаях для этого требуется сборщик-мусора.
Примечания
Ссылки