Passing arguments into function by value vs. DRY rule

Hey,

I have one problem. I realized that lua passing argument function by value not by reference ( what’s gives me opportunity to change original object ).

For example:

local mySimpleFunction = function( obj) print("Inside function: " .. obj) obj = obj + 1 print("Inside function: " .. obj) end local someObject = 1 print( "Before = " .. someObject) -- gives me 1 mySimpleFunction( someObject) -- 1 and 2 print( "After = " .. someObject) -- again gives me 1

But what if I have some kind of object which repeats a lot in my game e.g. monsters 

local monster1 = display.newImage( "monster.jpg", 100, 400 ) local monster2 = display.newImage( "monster.jpg", 200, 400 ) local monster3 = display.newImage( "monster.jpg", 300, 400 ) etc...... physics.addBody( monster1, "dyamic", { density=10.0, friction=1, bounce = 0} ) physics.addBody( monster2, "dyamic", { density=10.0, friction=1, bounce = 0} ) physics.addBody( monster3, "dyamic", { density=10.0, friction=1, bounce = 0} ) etc.....

And I want to make them to start moving. Some monster will be walking to the left, other to the right direction. With different velocity etc.

I don’t want to make new function for that to each monster (DRY - don’t repeat yourself). I want to write some general function 

local moveMonster = function( monster, direction, velocity) ...... end

and use it like this

local timerMonster1 = timer.performWithDelay( 500, function() moveMonster( monster1, left, 60); end, 0) local timerMonster2 = timer.performWithDelay( 250, function() moveMonster( monster2, right, 10); end, 0) local timerMonster3 = timer.performWithDelay( 1000, function() moveMonster( monster3, right, 30); end, 0)

Other general function can be ‘killMonster’ where I’ll use ‘removeSelf()’ for this monster.

I need to do all this stuff to orginal object not a copy. 

Do you have any solution to solve this?

I’m not sure I understand your question, but I’ll outline some Lua and Corona facts and let you apply them as you see fit.

1 - Lua functions accept tables as arguments, which allows you to parameterize info passed to a function:

local function changeName( obj, newName ) obj.name = newName end local testObj = {} testObj.name = "bob" print(testObj.name) -- prints: bob changeName( testObj, "billy" ) -- changes testObj which is passed by reference print( testObj.name ) -- prints: billy

Note: Above was example of passing table, not of parameterization.  Here is an example of that:

local function newCircle( x, y, params } params = params or {} local color = params.color or { 1,1,1 } local radius = params.radius or 10 local tmp = display.newCircle( x, y, radius ) tmp:setFillColor( unpack( color ) ) return tmp end newCircle( 10, 10, { color = { 1,0,0 } } ) -- red circle of radius 10 at \<10,10\> newCircle( 50, 50, { color = { 1,1,0 }, radius = 15 } ) -- yellow circle of radius 15 at \<50,50\> newCircle( 100, 100 ) -- White circle of radius 10 at \<100,100\>
  1. Lua allows you attach functions to tables as methods.  Thus we could write the above example as follows:

    – Note: ‘self’ is simply a naming convention, you can call the argument anything local function changeName( self, newName ) self.name = newName end local testObj = {} testObj.name = “bob” testObj.change = changeName – Assign function as field on our table. – This lets us re-use the function local testObj2 = {} testObj2.name = “bud” testObj2.change = changeName – Assign function as field on our table. print(testObj.name) – prints: bob print(testObj2.name) – prints: bud testObj:change( “billy” ) testObj2:change( “edo” ) print(testObj.name) – prints: billy print(testObj2.name) – prints: edo

  2. For ‘all’ callbacks and most closures, Corona uses a smart method naming trick.

    – This works… – local function agePlayer( obj ) obj.age = obj.age + 1 end local player = {} player.age = 10 timer.performWithDelay( 500, function() agePlayer( player ) end, 10 ) – Age ever 500ms, 10 times – This is better: – local function agePlayer( obj ) obj.age = obj.age + 1 end local player = {} player.age = 10 player.timer = agePlayer – ‘timer’ is a special method looked for by performWithDelay timer.performWithDelay( 500, player, 10 ) – Same as before, but pass the table directly.

This trick works for a lot of case, like:

  • obj.touch = function( self, event ) – Table listener for touch events
  • obj.collision = function( self, event ) – Table listener for collision events
  • obj.preCollision = function( self, event ) – Table listener for pre-collision events
  1. The above trick can also be used for custom events:

    local function onShout( self, event ) print( self.name … " says " … event.msg ) end local player1 = {} player1.name = “bill” player1.onShout = onShout Runtime:addEventListener( “onShoult”, player1 ) local player2 = {} player2.name = “bob” player2.onShout = onShout Runtime:addEventListener( “onShoult”, player2 ) Runtime:dispatchEvent( { name = “onShout”, msg = “Yo!” } ) – When the last line runs, the console shows: – bill says Yo! – bob says Yo!

  2. All of the above is true of display objects, which are treated like tables by Lua.

  3. Lua + Corona == flexible and easy to code

Thanks a lot. This is what I needed.

I’m not sure I understand your question, but I’ll outline some Lua and Corona facts and let you apply them as you see fit.

1 - Lua functions accept tables as arguments, which allows you to parameterize info passed to a function:

local function changeName( obj, newName ) obj.name = newName end local testObj = {} testObj.name = "bob" print(testObj.name) -- prints: bob changeName( testObj, "billy" ) -- changes testObj which is passed by reference print( testObj.name ) -- prints: billy

Note: Above was example of passing table, not of parameterization.  Here is an example of that:

local function newCircle( x, y, params } params = params or {} local color = params.color or { 1,1,1 } local radius = params.radius or 10 local tmp = display.newCircle( x, y, radius ) tmp:setFillColor( unpack( color ) ) return tmp end newCircle( 10, 10, { color = { 1,0,0 } } ) -- red circle of radius 10 at \<10,10\> newCircle( 50, 50, { color = { 1,1,0 }, radius = 15 } ) -- yellow circle of radius 15 at \<50,50\> newCircle( 100, 100 ) -- White circle of radius 10 at \<100,100\>
  1. Lua allows you attach functions to tables as methods.  Thus we could write the above example as follows:

    – Note: ‘self’ is simply a naming convention, you can call the argument anything local function changeName( self, newName ) self.name = newName end local testObj = {} testObj.name = “bob” testObj.change = changeName – Assign function as field on our table. – This lets us re-use the function local testObj2 = {} testObj2.name = “bud” testObj2.change = changeName – Assign function as field on our table. print(testObj.name) – prints: bob print(testObj2.name) – prints: bud testObj:change( “billy” ) testObj2:change( “edo” ) print(testObj.name) – prints: billy print(testObj2.name) – prints: edo

  2. For ‘all’ callbacks and most closures, Corona uses a smart method naming trick.

    – This works… – local function agePlayer( obj ) obj.age = obj.age + 1 end local player = {} player.age = 10 timer.performWithDelay( 500, function() agePlayer( player ) end, 10 ) – Age ever 500ms, 10 times – This is better: – local function agePlayer( obj ) obj.age = obj.age + 1 end local player = {} player.age = 10 player.timer = agePlayer – ‘timer’ is a special method looked for by performWithDelay timer.performWithDelay( 500, player, 10 ) – Same as before, but pass the table directly.

This trick works for a lot of case, like:

  • obj.touch = function( self, event ) – Table listener for touch events
  • obj.collision = function( self, event ) – Table listener for collision events
  • obj.preCollision = function( self, event ) – Table listener for pre-collision events
  1. The above trick can also be used for custom events:

    local function onShout( self, event ) print( self.name … " says " … event.msg ) end local player1 = {} player1.name = “bill” player1.onShout = onShout Runtime:addEventListener( “onShoult”, player1 ) local player2 = {} player2.name = “bob” player2.onShout = onShout Runtime:addEventListener( “onShoult”, player2 ) Runtime:dispatchEvent( { name = “onShout”, msg = “Yo!” } ) – When the last line runs, the console shows: – bill says Yo! – bob says Yo!

  2. All of the above is true of display objects, which are treated like tables by Lua.

  3. Lua + Corona == flexible and easy to code

Thanks a lot. This is what I needed.