Sign in to follow this  
Balaam

Lua: References

Recommended Posts

I think my language terminology is failing me here so I'll let my code talk I want anything passed into my function as an argument to stay constant. I don't want the function to change it.
--[[
    Function: NoReplacePick
    Randomly pick from an array without replacement.

	a = {1, 2, 3, 4, 5};
	NoReplacePick(a) -> 2, {1, 3, 4, 5};

    Parameters:

	pickTable - The table that we randomly pick from.

    Returns:

	pick - Element picked.
	modified pick table - pickTable with pick removed.

--]]
function NoReplacePick(pickTable)

    --Choose a random number from 1 to pickTable length
  
    local r = math.random(table.getn(pickTable));
    
    --Swap first pickTable entry with another random entry
    
    pickTable[1], pickTable[r] = pickTable[r], pickTable[1];

    --Pick without replacement the first element in pickTable

    local pick = pickTable[1];
    table.remove(pickTable, 1);

    --Return pick and modified pickTable
    return pick, pickTable;

end    
Now if I have:

a = {1,2,3,4,5}; --5 elements
pickTable(a);
-- a has 4 elements I want it to remain 5
Is there a special keyword I can use so it makes a copy rather than uses a reference? I tried making a local pickTableTemp variable than assigned pickTable to it (pickTableTemp = pickTable). I did this at start of the function and then only made reference to pickTableTemp but I had the same results. My searches haven't been much use because I'm not sure which words to use :( Any help would be appreciated. [Edited by - Balaam on August 30, 2005 4:58:01 AM]

Share this post


Link to post
Share on other sites
I think all function arguments in Lua are by reference. Your best bet is probably to take a copy of the table in the function and operate on that. I'm surprised I couldn't find a table copying function in Lua, but it should just be a simple 2 or 3 line loop.

Share this post


Link to post
Share on other sites
Thanks I think you're right. If any one else is having a similar issue here's some code from the Lua Email List:


function clone(node)
if type(node) ~= "table" then return node end
local b = {}
table.foreach(node, function(k,v) b[k]=clone(v) end)
return b
end

Share this post


Link to post
Share on other sites
Function calls in Lua are by value, not by reference. But tables are referred to by reference types. So if you want to modify a table in-place and yet not have it affect the original table, you'll have to copy it. (There are more efficient ways, involving metatables.... tell me if you're curious about those.)

Share this post


Link to post
Share on other sites
Alright. The key is that the __index metafunction can be a table rather than a function. If it's a table, lookups into the enclosing table which fail are deferred to the __index table. So you can do something like this:

mastertable = { a = 3, b = 4 } -- the table we don't want to mess with

slavetable = {} -- a table that will pretend to be mastertable

setmetatable(slavetable, { __index = mastertable }) -- where the magic happens.

print(slavetable.a) -- prints "3"
slavetable.b = 5 -- makes a new entry in slavetable, overriding but not changing the one in mastertable
print(slavetable.b) -- prints "5" (found in the slave table)
print(mastertable.b) -- prints "4"




Note that this code is from memory... I don't usually use this method.

Share this post


Link to post
Share on other sites
Cheers that looks quite interesting. Everything is working now but I think I'd like to play with this too. My tables are potentially going to be quite big and therefore cloning is quite expensive.

Share this post


Link to post
Share on other sites

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