How do you manipulate parameters you've passed into a function?

Hi everyone!

I’m very new to programming in general and only picked up Corona SDK earlier today, so apologies if I am not coming across clearly or using the wrong lingo (please correct me if I do).

I’m working on a simple card game to learn more about working with Corona and lua but eventually ran into a problem not covered in the tutorials I read and found no answers after much searching.

In short, my question is this: when you pass a parameter into a function, how do you go about manipulating/altering that parameter within the function using the label that you passed in?

If that question doesn’t make any sense, here’s what I mean by example:

[lua]

local function shuffleDeck( anyDeck )

    

    --code

    anyDeck = temporaryShufflingDeck

end

[/lua]

Obviously I’ve left out the vast majority of the code for simplification here (I can provide it if it would help, but I don’t think it’s necessary for this question). The deck I pass in here is a table called “p1Deck”. If I type:

[lua]

local function shuffleDeck( anyDeck )

    

    --code

    p1Deck = temporaryShufflingDeck

end

[/lua]

before the end instead (thus hardcoding the variable p1Deck into the function), then p1Deck is correctly set to equal temporaryShufflingDeck. However I want the function to set which ever deck I pass in to temporaryShufflingDeck so that the function will work on other potential decks that I want to pass in. Apparently simply using the parameter label (anyDeck) does not work, so how would I go about manipulating any deck passed in using the label anyDeck for versatility?

Thank you for your time and consideration.

local function shuffleDeck( anyDeck )   return temporaryShufflingDeck   end   p1Deck = shuffleDeck(p1Deck)

Hi jstrahan, thank you very much for the response. I’ve tried this approach and it works, however I dislike leaving the extra step of setting the deck outside of the function, and inability to set it inside the function causes issues for other functions I’ve been working on. Is there really no way to manipulate the passed-in parameter in a versatile way while still inside of the function?

local decks = { p1Deck = { }, p2Deck = { } ) local function shuffleDeck( anyDeck )   decks[anyDeck] = temporaryShufflingDeck   end  

anyDeck would be a string ie. “p1Deck”

is that what you looking for

The way I currently have the program set up, decks (such as p1Deck) are a table of cards. Cards in turn are tables of various other characteristics such as a name string, a number, etc.

I do not currently have the decks themselves in a table, which is what you appear to do on line 1 there. Is that necessary to reference the parameter inside the function without hardcoding a specific one? My gut tells me there should be a way to reference it directly without using an extra table (since it has already been passed in after all).

After some more digging I found something interesting:

http://stackoverflow.com/questions/6128152/lua-function-variable-scope-pass-by-value-or-reference

which immediately suggested to me that it should be possible to alter the table via direct reference in the function. Indeed, I created a similar small scale section of code like the one in the link and found that I could alter a table if I acted on its keys. In other words, this works:

[lua]

local t1 = { 0, 2, 3 }

local function modt ( randomTable )

    randomTable[1] = 10

    randomTable[2] = 20

    randomTable[3] = 30

end

modt(t1)

[/lua]

t1 prints with the new values. However I then tried making it more like my code, setting t1 in its entirety equal to a table built in the function:

[lua]

local t1 = { 0, 2, 3 }

local function modt ( randomTable )

    local t2 = { 10, 20, 30 }

    randomTable = t2

end

modt(t1)

[/lua]

and that does not work. t1 is not set to t2.

This isolates the issue as I see it. Why can you use the parameter reference for a table to set its components one at a time, but you can’t set the whole thing in one go? Surely it must be possible, but I am doing something wrong. Any help would be appreciated!

That’s cause randomTable is a copy of t1 it’s not really t1

Maybe not just woke up let me retread that

@nick14,

Nope.  That second piece of code won’t work.  

t1 - Contains a reference to a table.

randomTable is a temporary local variable in the the function modt(). As you’ve written the code, this variable contains a reference to the SAME table referred to by t1.  You’re thinking of this as if it were a reference to the variable t1, which it is not.

To reduce this problem to its fundamental parts, try this code:

local t1 = { "Bob" } -- \<\< t1 refers to Table 'A' local t2 = { "Buddy" } -- \<\< t2 refers to Table 'B' local t3 = t1 -- \<\< t3 refers to Table 'A' print(t1,t2,t3) -- Prints reference IDs of Table A, Table B, Table A print( t1[1], t2[1], t3[1] ) -- Prints "Bob", "Buddy", "Bob" t1 = t2 -- t1 now refers to Table 'B', not variable t2 print(t1,t2,t3) -- Prints reference IDs of Table B, Table B, Table A -- i.e. Table A still exists (is referred to in t3) print( t1[1], t2[1], t3[1] ) -- Prints "Buddy", "Buddy", "Bob" t1 = t3 -- t1 now refers to Table 'A', not variable t3 print(t1,t2,t3) -- Prints reference IDs of Table A, Table B, Table A -- i.e. same as original table references print( t1[1], t2[1], t3[1] ) -- Prints "Bob", "Buddy", "Bob"&nbsp;

Sorry for the edits, but I was clarifying and cleaning the sample.

@roaminggamer

Many thanks for the write-up, I spent a good half hour absorbing it and playing with it, and it was very insightful for me.

I still don’t fully understand the original issue however. I will try to explain it in another way. Please note I am only changing line 5 in each example.

[lua]
local t1 = { 0 }

print( t1[1] ) – prints 0

local function modta ( tt )
local t2 = { 1 }
t1[1] = t2[1]
end

modta( t1 )

print( t1[1] ) – prints 1
[/lua]

Setting the first key that t1 references to the same as t2’s first key works. After the function is complete, t1 prints the key originally assigned to t2 inside the function.

[lua]
local t1 = { 0 }

print( t1[1] ) – prints 0

local function modtb ( tt )
local t2 = { 1 }
t1 = t2
end

modtb( t1 )

print( t1[1] )-- prints 1
[/lua]

Setting t1 to reference the table t2 references also works. After the function t1 prints the key originally assigned to t2.

[lua]
local t1 = { 0 }

print( t1[1] )-- prints 0

local function modtc ( tt )
local t2 = { 1 }
tt[1] = t2[1]
end

modtc( t1 )

print( t1[1] )-- prints 1
[/lua]

Here we get into what I would like to do. Instead of using t1 directly I would like to use the parameter label of the function (tt) so that the function works on any table passed in. And it works when I reference a specific key as done above!

[lua]
local t1 = { 0 }

print( t1[1] )-- prints 0

local function modtd ( tt )
local t2 = { 1 }
tt = t2
end

modtd( t1 )

print( t1[1] )-- prints 0!
[/lua]

But then I try to accomplish the ultimate goal of using the parameter label (tt) to have a table passed in (t1 in this case) reference what t2 references in its entirety (just like in the second example, but using the parameter label this time), rather than changing each key as in the third example. This doesn’t work! Based on the previous examples, I would expect this to work.

Why can you use the parameter label (tt) to change references for individual keys but not the entire table? And what’s the best way to get the job done? Do you really have to use a for loop and alter every key reference individually?

@nick,

I’ll discuss what is happening in each of your snippets.

1. Snippet 1 - t1 ( the local ) is visible to your function because your function is written after you declared t1.  Thus, the function can access the variable and the table it references.  Try  example A below and notice that the order change causes it NOT to work.

2. Snippet 2 -  Same situation.  This only works because of scope and order.  See Example B below where I change the order and your code stops working.

3. Snippet 3 - In this case, tt contains a reference to the table as I explained before so it works fine regardless of scope or order.  See Example C below to prove that scope and order don’t matter.

4. Snippet 4 - This is basically what I talked about above.  The variable tt in your final snippet contains a reference to the table that t1 points to, not a reference to the variable t1.  The ID/handle of the table stored in variable t1 is passed to the function and stored in the temporary variable tt.  When you replace the contents of the variable tt, you are not changing the contents of t1.   Neither are you replacing the contents of the table t1 refers to.   There is NO way to get references to variables.  Lua doesn’t work that way.   Note, because you so very much want to do this, you may not realize that if Lua did work this way, the language would be quite terrible and error prone.  People would accidentally replace tables all the time.

Answer to your question:

If you want to replace the contents of a table whose reference is passed to a function, you must iterate over that reference and replace each individual indexed entry.  Alternately, you can replace the table by returning a new table from your function.  See example D below  Again, there is absolutely no way to replace a table (outside the scope and visibility of the function) directly.  

Example A

local function modta ( tt ) &nbsp; &nbsp;local t2 = { 1 } &nbsp; &nbsp;t1[1] = t2[1] end local t1 = { 0 } print( t1[1] ) -- prints 0 modta( t1 ) print( t1[1] ) -- prints 0 (unlike your prior example snippet 1)

Example B

local function modtb ( tt ) &nbsp; &nbsp;local t2 = { 1 } &nbsp; &nbsp;t1 = t2 end local t1 = { 0 } print( t1[1] ) -- prints 0 modtb( t1 ) print( t1[1] )-- prints 0 (again not like snippet 2 above)&nbsp;

Example C

local function modtc ( tt ) &nbsp; &nbsp;local t2 = { 1 } &nbsp; &nbsp;tt[1] = t2[1] end local t1 = { 0 } print( t1[1] )-- prints 0 modtc( t1 ) print( t1[1] )-- prints 1&nbsp;(Still works because you're passing a reference to the table)

Example D

-- This function returns a table which can then be assigned to a variable if you wish&nbsp; -- Note: This example is only showing mechanics, and is not otherwise useful local function modtc ( tt ) &nbsp; &nbsp;local t2 = { 1 } &nbsp; &nbsp;return t2&nbsp; end local t1 = { 0 } print( t1[1] )-- prints 0 t1 = modtc( t1 ) print( t1[1] )-- prints 1&nbsp;

@roaminggamer

Thank you very much for taking the time to explain everything.

My main confusion surrounded why snippet 3 worked but snippet 4 did not. My understanding of it after reading your explanation is that tt[1] = t2[1] is altering elements in the table itself, whereas tt = t2 is only altering the variable tt which references said table (thus t1, which only reads the table, does not pick up the change). Does that sound right?

Given that this is the case and what you’ve presented regarding order and scope, I can think of a few ways to proceed.

  1. Go the example D route (this was actually the first workaround I used, as I mentioned earlier, but I discarded it because it didn’t seem elegant and I thought there would be a better way).

  2. Iterate inside the function to set each key.

  3. Now that you mentioned scope I just thought of this: declare a placeholder variable before the function to be used specifically for this function.

I don’t want to take much more of your time, but if off the top of your head you think any of these ideas are particularly good or bad I would love to hear why briefly!

Yes, that is exactly right.  The core of the issue is that you can can’t pass variables by reference, only Objects and Tables.

All those options will work, but I often use option 3 if I know I won’t be modifying the code or moving it around later.  It isn’t exactly elegant (heck it’s simply a cheat taking advantage of scope and visibility rules), but making a game/app isn’t about elegance.  It is about getting the code written and working (well).  This option has the benefit of speed, whereas 2 is slow(er). 

Cheers,

Ed

I understand. Well once again, thank you so much for taking the time! I’ve learned a great deal from your posts (more than I had originally planned for, and that’s a good thing).

local function shuffleDeck( anyDeck ) &nbsp; return temporaryShufflingDeck &nbsp; end &nbsp; p1Deck = shuffleDeck(p1Deck)

Hi jstrahan, thank you very much for the response. I’ve tried this approach and it works, however I dislike leaving the extra step of setting the deck outside of the function, and inability to set it inside the function causes issues for other functions I’ve been working on. Is there really no way to manipulate the passed-in parameter in a versatile way while still inside of the function?

local decks = { p1Deck = { }, p2Deck = { } ) local function shuffleDeck( anyDeck ) &nbsp; decks[anyDeck] = temporaryShufflingDeck &nbsp; end &nbsp;

anyDeck would be a string ie. “p1Deck”

is that what you looking for

The way I currently have the program set up, decks (such as p1Deck) are a table of cards. Cards in turn are tables of various other characteristics such as a name string, a number, etc.

I do not currently have the decks themselves in a table, which is what you appear to do on line 1 there. Is that necessary to reference the parameter inside the function without hardcoding a specific one? My gut tells me there should be a way to reference it directly without using an extra table (since it has already been passed in after all).

After some more digging I found something interesting:

http://stackoverflow.com/questions/6128152/lua-function-variable-scope-pass-by-value-or-reference

which immediately suggested to me that it should be possible to alter the table via direct reference in the function. Indeed, I created a similar small scale section of code like the one in the link and found that I could alter a table if I acted on its keys. In other words, this works:

[lua]

local t1 = { 0, 2, 3 }

local function modt ( randomTable )

    randomTable[1] = 10

    randomTable[2] = 20

    randomTable[3] = 30

end

modt(t1)

[/lua]

t1 prints with the new values. However I then tried making it more like my code, setting t1 in its entirety equal to a table built in the function:

[lua]

local t1 = { 0, 2, 3 }

local function modt ( randomTable )

    local t2 = { 10, 20, 30 }

    randomTable = t2

end

modt(t1)

[/lua]

and that does not work. t1 is not set to t2.

This isolates the issue as I see it. Why can you use the parameter reference for a table to set its components one at a time, but you can’t set the whole thing in one go? Surely it must be possible, but I am doing something wrong. Any help would be appreciated!

That’s cause randomTable is a copy of t1 it’s not really t1