Sign in to follow this  
Mr_Bob

Вопрос по таблицам, почему так происходит

Recommended Posts

В общем вот пример:

function sdsssss(var) 
    local var2= var 
    var2[2] = "ssss" 
    outputChatBox(var[1].." "..var[2]) --> "1 ssss" 
    outputChatBox(var2[1].." "..var2[2])--> "1 ssss" 
end 
sdsssss({1,2}) 

Почему вторая строка меняется так же и в "оригинальной" таблице? Как выйти из этой ситуации (кроме цикла со вносом каждой строки в новую таблицу)?

Share this post


Link to post

Во время присваивания значения с типом таблицы, в переменную заносится только адрес этой таблицы. Выйти из ситуации можно банально копированием таблицы. Например при помощи вот такой простой функции:

function table.copy ( t ) 
  local tbl2 = { } 
  for k, v in pairs ( t ) do 
    tbl2 [ k ] = v 
  end 
  return tbl2 
end 
  

Share this post


Link to post

Это понятно. А если вот передаю таблицу с сервера клиенту, на клиенте делаю следующее:

function receiveNewStats(stats_table) 
    client_stats_table = stats_table 
end 

Получается, что таблица stats_table все время висит в памяти клиента?

Share this post


Link to post

В Lua переменная живёт пока: 1. на неё есть ссылки; 2. переменная не выйдет из области видимости.

Если переменная в глобальной области видимости - то да, она постоянно будет висеть в памяти. Если ранее нигде область видимости не задавалась - то переменная автоматически становится глобальной.

Share this post


Link to post
В Lua переменная живёт пока: 1. на неё есть ссылки; 2. переменная не выйдет из области видимости.

Если переменная в глобальной области видимости - то да, она постоянно будет висеть в памяти. Если ранее нигде область видимости не задавалась - то переменная автоматически становится глобальной.

Это не совсем так.

Принцип верен, но все немного сложнее, Луа работает не так как остальные языки.

В Луа используется такой термин как среда (environment), _G - это ссылка на глобальную среду внутри глобальной среды (ссылка на саму себя), но каждая функция выполняется в своей среде. Мы знаем что среда - это лишь таблица, а следовательно, для каждой функции существует своя таблица, записи в которую заносятся оператором local.

Для тех кто знаком с мета таблицами, понятнее будет так:

local env = {} 
setmetatable ( env, { __index = _G } ) 
function f () end 
setfenv ( f, env ) 
  

Это то что делает Луа.

Для тех кто не в курсе, __index метаметод действует следующим образом: Если в таблице не найдено значение, поиск ведется в __index таблице.

А функцией setfenv можно поменять среду, сделав так что внутри функции будут недоступны даже глобальные переменные.

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

Пример:

function a () 
    local test = "boo" 
    local b = function () 
      outputChatBox ( test ) 
    end 
    addEventHandler ( "onPlayerJoin", getRootElement(), b ) 
end 
a() 

В данном случае, когда на сервер будет заходить игрок, всегда будет выводиться в чат "boo", не смотря на то что и переменная test и функция boo были локальными. Ссылку на функцию b хранит МТА, а к функции b присвоена среда которая зависит от среды фукции a.

З.Ы. Каждый файл в ресурсе можно рассматривать как функцию, потому что на самом деле мта лишь загружает сожержимое файла в loadstring, которая возвращает функцию. Таким образом и для каждого файла может существовать своя переменная.

З.Ы.Ы. Это не описывают в уроках по Луа, может кому-нибудь будет интересно.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.