• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua position changed, why?

roriscrave

Advanced OT User
Joined
Dec 7, 2011
Messages
1,188
Solutions
34
Reaction score
200
Why positionTWO changed positionOne? how can i do that position2 will not change position one?

Lua:
   local positionONE = Position(100, 100, 7)
    local positionTWO = positionONE
    positionTWO.x = 500   
   
    print("positionONE:", positionONE.x, positionONE.y, positionONE.z)
    print("positionTWO:", positionTWO.x, positionTWO.y, positionTWO.z)

1609045855160.png
 
Solution
because positionTWO is just a reference
try local positionTWO = Position(positionONE) or local positionTWO = Position(positionONE.x, positionONE.y, positionONE.z)
because positionTWO is just a reference
try local positionTWO = Position(positionONE) or local positionTWO = Position(positionONE.x, positionONE.y, positionONE.z)
 
Solution
I wrote one 25 days ago

The full version of deep copy, handling all the 3 situations:
  1. Table circular reference
  2. Keys which are also tables
  3. Metatable
The general version:

Lua:
local function deepcopy(o, seen)
  seen = seen or {}
  if o == nil then return nil end
  if seen[o] then return seen[o] end

  local no
  if type(o) == 'table' then
    no = {}
    seen[o] = no

    for k, v in next, o, nil do
      no[deepcopy(k, seen)] = deepcopy(v, seen)
    end
    setmetatable(no, deepcopy(getmetatable(o), seen))
  else -- number, string, boolean, etc
    no = o
  end
  return no
end

Or the table version:

Lua:
function table.deepcopy(o, seen)
  seen = seen or {}
  if o == nil then return nil end
  if seen[o] then return seen[o] end


  local no = {}
  seen[o] = no
  setmetatable(no, deepcopy(getmetatable(o), seen))

  for k, v in next, o, nil do
    k = (type(k) == 'table') and k:deepcopy(seen) or k
    v = (type(v) == 'table') and v:deepcopy(seen) or v
    no[k] = v
  end
  return no
end

Based on the lua-users.org/wiki/CopyTable's and Alan Yates' functions.
 
Nice. For some reason I overlooked that month ago. Not sure if it's safe to duplicate Creature or Item object though (potential crash?). Might be why I didn't do that.

Anyway, I'm pretty sure that a simple rewriting of the Position will be enough to solve thread author's problem, but that's also good to know.
 
You can simply make a copy of a table, passing a table to a new table as the only argument
example: TABLE2 = {TABLE}
Lua:
TABLE = { X=100, Y=100, Z=7 }
TABLE2 = {TABLE}

TABLE2.X = 5000
print(TABLE2.X, TABLE.X)
output: 5000 100

I was wrong I'm sorry

this method only works for tables with numeric indexes and is:
local a = {unpack(TABLE)}
 
Last edited:
You can simply make a copy of a table, passing a table to a new table as the only argument
example: TABLE2 = {TABLE}
Lua:
TABLE = { X=100, Y=100, Z=7 }
TABLE2 = {TABLE}

TABLE2.X = 5000
print(TABLE2.X, TABLE.X)
output: 5000 100
doesn't that result in this?
{x = 5000, [1] = {x = 100, y = 100, z = 7}}

edit: yes, it does
print(TABLE2.X, TABLE.X, TABLE2[1]) -> 5000 100 table: 0x13188e0
 
roriscrave

FYI, the code you showed at the start of the thread is actually the classic example for explaining references.

Unfortunately most discussions on the web about this are full of complete rubbish, so it's quite hard to get good information quickly. In particular, never pay attention to any discussion of "pass by value vs pass by reference" that takes more than 5 posts :)

There's an easy way to treat this though:
Considered as data, references act like "primitives" (what the LUA article on wikipedia calls "atomic data structures") If you execute refA = refB, then refA gets the same value as refB. It does not get a copy of the value(s) of the table (object in OO languages) that refB references.

Your example demonstrates this perfectly.

This bit is based on Java, but AFAIK it's also true for LUA:
In Java, you can put references to objects into an object (and you do this a lot). In that case, making a new object using the approach suggested by Nekiro's above would copy the references in the outer object rather than make a copy of the "inner objects" referred to by fields in the outer object. (BTW Nekiro's approach is 100% correct for your example)

This distinction isn't usually noticeable to a developer, but occasionally it matters. Funnily enough a case where it's visible turned up in the "tree cutting" example I'll share with you soon, so you can see a live example later.


(BTW I didn't check Switch's example above, but it looks promising. The usual terminology for copying an entire table/object, including inner tables/objects is "deep copy" or "clone", both of which are used in Switch's post.)
 
Last edited:
Back
Top