LUA: Avoiding passing by reference










1















I'm just starting to learn LUA and I've got an issue that I'm unsure which way to "properly" solve.
When I pass a Defold vmath.vector3 to my function it appears to be passed by reference and is therefore altered.

If I multiply it by anything this is solved however.

Is there another more correct way to solve this? I don't want to modify the original vector that I pass as an argument.



function M.get_nearest_tile(x, y)
if y then -- if we've got 2 inputs, use x & y
x = math.floor(x / M.TILE_SIZE)
y = math.floor(y / M.TILE_SIZE)
return x, y
else -- if we've only got 1 input, use as vector
local vec = x * 1 -- multiplying by 1 to avoid modifying the real vector
vec.x = math.floor(vec.x / M.TILE_SIZE)
vec.y = math.floor(vec.y / M.TILE_SIZE)
return vec.x, vec.y
end
end









share|improve this question
























  • Where does vector3 come from? Is this Roblox or so?

    – Henri Menke
    Nov 13 '18 at 22:15











  • Ah, sorry, I feel stupid. I thought it was from "math". It's from "vmath" which is used by Defold (game engine).

    – Ghork
    Nov 13 '18 at 22:18






  • 1





    According to the docs you can copy a vector using local new = vmath.vector3(old) defold.com/ref/vmath/#vmath.vector3:v1

    – Henri Menke
    Nov 13 '18 at 22:19






  • 1





    Nitpick: It is Lua, not LUA.

    – britzl
    Nov 14 '18 at 5:04






  • 1





    You would get the same kind of result when passing a table. As Henri Menke mentioned above it is non-trivial to copy a Lua table.

    – britzl
    Nov 14 '18 at 5:05















1















I'm just starting to learn LUA and I've got an issue that I'm unsure which way to "properly" solve.
When I pass a Defold vmath.vector3 to my function it appears to be passed by reference and is therefore altered.

If I multiply it by anything this is solved however.

Is there another more correct way to solve this? I don't want to modify the original vector that I pass as an argument.



function M.get_nearest_tile(x, y)
if y then -- if we've got 2 inputs, use x & y
x = math.floor(x / M.TILE_SIZE)
y = math.floor(y / M.TILE_SIZE)
return x, y
else -- if we've only got 1 input, use as vector
local vec = x * 1 -- multiplying by 1 to avoid modifying the real vector
vec.x = math.floor(vec.x / M.TILE_SIZE)
vec.y = math.floor(vec.y / M.TILE_SIZE)
return vec.x, vec.y
end
end









share|improve this question
























  • Where does vector3 come from? Is this Roblox or so?

    – Henri Menke
    Nov 13 '18 at 22:15











  • Ah, sorry, I feel stupid. I thought it was from "math". It's from "vmath" which is used by Defold (game engine).

    – Ghork
    Nov 13 '18 at 22:18






  • 1





    According to the docs you can copy a vector using local new = vmath.vector3(old) defold.com/ref/vmath/#vmath.vector3:v1

    – Henri Menke
    Nov 13 '18 at 22:19






  • 1





    Nitpick: It is Lua, not LUA.

    – britzl
    Nov 14 '18 at 5:04






  • 1





    You would get the same kind of result when passing a table. As Henri Menke mentioned above it is non-trivial to copy a Lua table.

    – britzl
    Nov 14 '18 at 5:05













1












1








1








I'm just starting to learn LUA and I've got an issue that I'm unsure which way to "properly" solve.
When I pass a Defold vmath.vector3 to my function it appears to be passed by reference and is therefore altered.

If I multiply it by anything this is solved however.

Is there another more correct way to solve this? I don't want to modify the original vector that I pass as an argument.



function M.get_nearest_tile(x, y)
if y then -- if we've got 2 inputs, use x & y
x = math.floor(x / M.TILE_SIZE)
y = math.floor(y / M.TILE_SIZE)
return x, y
else -- if we've only got 1 input, use as vector
local vec = x * 1 -- multiplying by 1 to avoid modifying the real vector
vec.x = math.floor(vec.x / M.TILE_SIZE)
vec.y = math.floor(vec.y / M.TILE_SIZE)
return vec.x, vec.y
end
end









share|improve this question
















I'm just starting to learn LUA and I've got an issue that I'm unsure which way to "properly" solve.
When I pass a Defold vmath.vector3 to my function it appears to be passed by reference and is therefore altered.

If I multiply it by anything this is solved however.

Is there another more correct way to solve this? I don't want to modify the original vector that I pass as an argument.



function M.get_nearest_tile(x, y)
if y then -- if we've got 2 inputs, use x & y
x = math.floor(x / M.TILE_SIZE)
y = math.floor(y / M.TILE_SIZE)
return x, y
else -- if we've only got 1 input, use as vector
local vec = x * 1 -- multiplying by 1 to avoid modifying the real vector
vec.x = math.floor(vec.x / M.TILE_SIZE)
vec.y = math.floor(vec.y / M.TILE_SIZE)
return vec.x, vec.y
end
end






function lua reference arguments defold






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 22:21









Henri Menke

7,62511327




7,62511327










asked Nov 13 '18 at 20:49









GhorkGhork

85




85












  • Where does vector3 come from? Is this Roblox or so?

    – Henri Menke
    Nov 13 '18 at 22:15











  • Ah, sorry, I feel stupid. I thought it was from "math". It's from "vmath" which is used by Defold (game engine).

    – Ghork
    Nov 13 '18 at 22:18






  • 1





    According to the docs you can copy a vector using local new = vmath.vector3(old) defold.com/ref/vmath/#vmath.vector3:v1

    – Henri Menke
    Nov 13 '18 at 22:19






  • 1





    Nitpick: It is Lua, not LUA.

    – britzl
    Nov 14 '18 at 5:04






  • 1





    You would get the same kind of result when passing a table. As Henri Menke mentioned above it is non-trivial to copy a Lua table.

    – britzl
    Nov 14 '18 at 5:05

















  • Where does vector3 come from? Is this Roblox or so?

    – Henri Menke
    Nov 13 '18 at 22:15











  • Ah, sorry, I feel stupid. I thought it was from "math". It's from "vmath" which is used by Defold (game engine).

    – Ghork
    Nov 13 '18 at 22:18






  • 1





    According to the docs you can copy a vector using local new = vmath.vector3(old) defold.com/ref/vmath/#vmath.vector3:v1

    – Henri Menke
    Nov 13 '18 at 22:19






  • 1





    Nitpick: It is Lua, not LUA.

    – britzl
    Nov 14 '18 at 5:04






  • 1





    You would get the same kind of result when passing a table. As Henri Menke mentioned above it is non-trivial to copy a Lua table.

    – britzl
    Nov 14 '18 at 5:05
















Where does vector3 come from? Is this Roblox or so?

– Henri Menke
Nov 13 '18 at 22:15





Where does vector3 come from? Is this Roblox or so?

– Henri Menke
Nov 13 '18 at 22:15













Ah, sorry, I feel stupid. I thought it was from "math". It's from "vmath" which is used by Defold (game engine).

– Ghork
Nov 13 '18 at 22:18





Ah, sorry, I feel stupid. I thought it was from "math". It's from "vmath" which is used by Defold (game engine).

– Ghork
Nov 13 '18 at 22:18




1




1





According to the docs you can copy a vector using local new = vmath.vector3(old) defold.com/ref/vmath/#vmath.vector3:v1

– Henri Menke
Nov 13 '18 at 22:19





According to the docs you can copy a vector using local new = vmath.vector3(old) defold.com/ref/vmath/#vmath.vector3:v1

– Henri Menke
Nov 13 '18 at 22:19




1




1





Nitpick: It is Lua, not LUA.

– britzl
Nov 14 '18 at 5:04





Nitpick: It is Lua, not LUA.

– britzl
Nov 14 '18 at 5:04




1




1





You would get the same kind of result when passing a table. As Henri Menke mentioned above it is non-trivial to copy a Lua table.

– britzl
Nov 14 '18 at 5:05





You would get the same kind of result when passing a table. As Henri Menke mentioned above it is non-trivial to copy a Lua table.

– britzl
Nov 14 '18 at 5:05












3 Answers
3






active

oldest

votes


















0














Since you're returning x and y as two values, you could implement both branches the same way without modifying any tables:



function M.get_nearest_tile(x, y)
local newX, newY
if y then -- if we've got 2 inputs, use x & y
newX = math.floor(x / M.TILE_SIZE)
newY = math.floor(y / M.TILE_SIZE)
else -- if we've only got 1 input, use as vector
newX = math.floor(x.x / M.TILE_SIZE)
newY = math.floor(x.y / M.TILE_SIZE)
end
return newX, newY
end





share|improve this answer

























  • You have a duplicate declaration of x and y, while syntactically not incorrect, this will not work as intended.

    – dualed
    Nov 14 '18 at 0:05











  • @dualed: Got it. Fixed.

    – luther
    Nov 14 '18 at 0:27






  • 1





    This is the kind of non-Defold specific but obvious solution I was looking for.

    – Ghork
    Nov 14 '18 at 9:27


















3














Defold provides a number of special data structures that are all very useful in game development:



  • vector3 - vmath.vector3(x,y,z), useful for describing positions or direction in a 3D coordinate system

  • vector4 - vmath.vector4(x,y,z,w), used for color, tint etc (red, green, blue, alpha)

  • quat - vmath.quat() a quaternion describing a rotation

  • matrix4 - vmath.matrix4() a 4x4 matrix of values. Useful for view and projection matrices among other things

All of the above are used by the Defold game engine, but you'll find the same kind of data structures in other game engines as well.



The data structures above have one thing in common: They are of the Lua type userdata



print(type(vmath.vector3())) -- "userdata"


User data is passed by reference always and that is why you're seeing the behaviour that you describe. Defold does provide ways to make copies though:




local copy = vmath.vector3(original) -- copy the vector3 'original'
local copy = vmath.vector4(original) -- copy the vector4 'original'
local copy = vmath.quat(original) -- copy the quaternion 'original'
local copy = vmath.matrix4(original) -- copy the matrix4 'original'






share|improve this answer






























    0














    You already have a solution in your else branch: you'll have to create a copy of your vectors before applying "modifying" operations to them.



    In terms of other options, it may be possible to come up with a way to do using proxy tables, but it's going to be much more complex than just creating a copy.






    share|improve this answer






















      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53289289%2flua-avoiding-passing-by-reference%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      0














      Since you're returning x and y as two values, you could implement both branches the same way without modifying any tables:



      function M.get_nearest_tile(x, y)
      local newX, newY
      if y then -- if we've got 2 inputs, use x & y
      newX = math.floor(x / M.TILE_SIZE)
      newY = math.floor(y / M.TILE_SIZE)
      else -- if we've only got 1 input, use as vector
      newX = math.floor(x.x / M.TILE_SIZE)
      newY = math.floor(x.y / M.TILE_SIZE)
      end
      return newX, newY
      end





      share|improve this answer

























      • You have a duplicate declaration of x and y, while syntactically not incorrect, this will not work as intended.

        – dualed
        Nov 14 '18 at 0:05











      • @dualed: Got it. Fixed.

        – luther
        Nov 14 '18 at 0:27






      • 1





        This is the kind of non-Defold specific but obvious solution I was looking for.

        – Ghork
        Nov 14 '18 at 9:27















      0














      Since you're returning x and y as two values, you could implement both branches the same way without modifying any tables:



      function M.get_nearest_tile(x, y)
      local newX, newY
      if y then -- if we've got 2 inputs, use x & y
      newX = math.floor(x / M.TILE_SIZE)
      newY = math.floor(y / M.TILE_SIZE)
      else -- if we've only got 1 input, use as vector
      newX = math.floor(x.x / M.TILE_SIZE)
      newY = math.floor(x.y / M.TILE_SIZE)
      end
      return newX, newY
      end





      share|improve this answer

























      • You have a duplicate declaration of x and y, while syntactically not incorrect, this will not work as intended.

        – dualed
        Nov 14 '18 at 0:05











      • @dualed: Got it. Fixed.

        – luther
        Nov 14 '18 at 0:27






      • 1





        This is the kind of non-Defold specific but obvious solution I was looking for.

        – Ghork
        Nov 14 '18 at 9:27













      0












      0








      0







      Since you're returning x and y as two values, you could implement both branches the same way without modifying any tables:



      function M.get_nearest_tile(x, y)
      local newX, newY
      if y then -- if we've got 2 inputs, use x & y
      newX = math.floor(x / M.TILE_SIZE)
      newY = math.floor(y / M.TILE_SIZE)
      else -- if we've only got 1 input, use as vector
      newX = math.floor(x.x / M.TILE_SIZE)
      newY = math.floor(x.y / M.TILE_SIZE)
      end
      return newX, newY
      end





      share|improve this answer















      Since you're returning x and y as two values, you could implement both branches the same way without modifying any tables:



      function M.get_nearest_tile(x, y)
      local newX, newY
      if y then -- if we've got 2 inputs, use x & y
      newX = math.floor(x / M.TILE_SIZE)
      newY = math.floor(y / M.TILE_SIZE)
      else -- if we've only got 1 input, use as vector
      newX = math.floor(x.x / M.TILE_SIZE)
      newY = math.floor(x.y / M.TILE_SIZE)
      end
      return newX, newY
      end






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 14 '18 at 0:27

























      answered Nov 13 '18 at 23:20









      lutherluther

      1,268614




      1,268614












      • You have a duplicate declaration of x and y, while syntactically not incorrect, this will not work as intended.

        – dualed
        Nov 14 '18 at 0:05











      • @dualed: Got it. Fixed.

        – luther
        Nov 14 '18 at 0:27






      • 1





        This is the kind of non-Defold specific but obvious solution I was looking for.

        – Ghork
        Nov 14 '18 at 9:27

















      • You have a duplicate declaration of x and y, while syntactically not incorrect, this will not work as intended.

        – dualed
        Nov 14 '18 at 0:05











      • @dualed: Got it. Fixed.

        – luther
        Nov 14 '18 at 0:27






      • 1





        This is the kind of non-Defold specific but obvious solution I was looking for.

        – Ghork
        Nov 14 '18 at 9:27
















      You have a duplicate declaration of x and y, while syntactically not incorrect, this will not work as intended.

      – dualed
      Nov 14 '18 at 0:05





      You have a duplicate declaration of x and y, while syntactically not incorrect, this will not work as intended.

      – dualed
      Nov 14 '18 at 0:05













      @dualed: Got it. Fixed.

      – luther
      Nov 14 '18 at 0:27





      @dualed: Got it. Fixed.

      – luther
      Nov 14 '18 at 0:27




      1




      1





      This is the kind of non-Defold specific but obvious solution I was looking for.

      – Ghork
      Nov 14 '18 at 9:27





      This is the kind of non-Defold specific but obvious solution I was looking for.

      – Ghork
      Nov 14 '18 at 9:27













      3














      Defold provides a number of special data structures that are all very useful in game development:



      • vector3 - vmath.vector3(x,y,z), useful for describing positions or direction in a 3D coordinate system

      • vector4 - vmath.vector4(x,y,z,w), used for color, tint etc (red, green, blue, alpha)

      • quat - vmath.quat() a quaternion describing a rotation

      • matrix4 - vmath.matrix4() a 4x4 matrix of values. Useful for view and projection matrices among other things

      All of the above are used by the Defold game engine, but you'll find the same kind of data structures in other game engines as well.



      The data structures above have one thing in common: They are of the Lua type userdata



      print(type(vmath.vector3())) -- "userdata"


      User data is passed by reference always and that is why you're seeing the behaviour that you describe. Defold does provide ways to make copies though:




      local copy = vmath.vector3(original) -- copy the vector3 'original'
      local copy = vmath.vector4(original) -- copy the vector4 'original'
      local copy = vmath.quat(original) -- copy the quaternion 'original'
      local copy = vmath.matrix4(original) -- copy the matrix4 'original'






      share|improve this answer



























        3














        Defold provides a number of special data structures that are all very useful in game development:



        • vector3 - vmath.vector3(x,y,z), useful for describing positions or direction in a 3D coordinate system

        • vector4 - vmath.vector4(x,y,z,w), used for color, tint etc (red, green, blue, alpha)

        • quat - vmath.quat() a quaternion describing a rotation

        • matrix4 - vmath.matrix4() a 4x4 matrix of values. Useful for view and projection matrices among other things

        All of the above are used by the Defold game engine, but you'll find the same kind of data structures in other game engines as well.



        The data structures above have one thing in common: They are of the Lua type userdata



        print(type(vmath.vector3())) -- "userdata"


        User data is passed by reference always and that is why you're seeing the behaviour that you describe. Defold does provide ways to make copies though:




        local copy = vmath.vector3(original) -- copy the vector3 'original'
        local copy = vmath.vector4(original) -- copy the vector4 'original'
        local copy = vmath.quat(original) -- copy the quaternion 'original'
        local copy = vmath.matrix4(original) -- copy the matrix4 'original'






        share|improve this answer

























          3












          3








          3







          Defold provides a number of special data structures that are all very useful in game development:



          • vector3 - vmath.vector3(x,y,z), useful for describing positions or direction in a 3D coordinate system

          • vector4 - vmath.vector4(x,y,z,w), used for color, tint etc (red, green, blue, alpha)

          • quat - vmath.quat() a quaternion describing a rotation

          • matrix4 - vmath.matrix4() a 4x4 matrix of values. Useful for view and projection matrices among other things

          All of the above are used by the Defold game engine, but you'll find the same kind of data structures in other game engines as well.



          The data structures above have one thing in common: They are of the Lua type userdata



          print(type(vmath.vector3())) -- "userdata"


          User data is passed by reference always and that is why you're seeing the behaviour that you describe. Defold does provide ways to make copies though:




          local copy = vmath.vector3(original) -- copy the vector3 'original'
          local copy = vmath.vector4(original) -- copy the vector4 'original'
          local copy = vmath.quat(original) -- copy the quaternion 'original'
          local copy = vmath.matrix4(original) -- copy the matrix4 'original'






          share|improve this answer













          Defold provides a number of special data structures that are all very useful in game development:



          • vector3 - vmath.vector3(x,y,z), useful for describing positions or direction in a 3D coordinate system

          • vector4 - vmath.vector4(x,y,z,w), used for color, tint etc (red, green, blue, alpha)

          • quat - vmath.quat() a quaternion describing a rotation

          • matrix4 - vmath.matrix4() a 4x4 matrix of values. Useful for view and projection matrices among other things

          All of the above are used by the Defold game engine, but you'll find the same kind of data structures in other game engines as well.



          The data structures above have one thing in common: They are of the Lua type userdata



          print(type(vmath.vector3())) -- "userdata"


          User data is passed by reference always and that is why you're seeing the behaviour that you describe. Defold does provide ways to make copies though:




          local copy = vmath.vector3(original) -- copy the vector3 'original'
          local copy = vmath.vector4(original) -- copy the vector4 'original'
          local copy = vmath.quat(original) -- copy the quaternion 'original'
          local copy = vmath.matrix4(original) -- copy the matrix4 'original'







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 14 '18 at 5:17









          britzlbritzl

          8,59462933




          8,59462933





















              0














              You already have a solution in your else branch: you'll have to create a copy of your vectors before applying "modifying" operations to them.



              In terms of other options, it may be possible to come up with a way to do using proxy tables, but it's going to be much more complex than just creating a copy.






              share|improve this answer



























                0














                You already have a solution in your else branch: you'll have to create a copy of your vectors before applying "modifying" operations to them.



                In terms of other options, it may be possible to come up with a way to do using proxy tables, but it's going to be much more complex than just creating a copy.






                share|improve this answer

























                  0












                  0








                  0







                  You already have a solution in your else branch: you'll have to create a copy of your vectors before applying "modifying" operations to them.



                  In terms of other options, it may be possible to come up with a way to do using proxy tables, but it's going to be much more complex than just creating a copy.






                  share|improve this answer













                  You already have a solution in your else branch: you'll have to create a copy of your vectors before applying "modifying" operations to them.



                  In terms of other options, it may be possible to come up with a way to do using proxy tables, but it's going to be much more complex than just creating a copy.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 13 '18 at 21:36









                  Paul KulchenkoPaul Kulchenko

                  19.4k22540




                  19.4k22540



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53289289%2flua-avoiding-passing-by-reference%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Darth Vader #20

                      How to how show current date and time by default on contact form 7 in WordPress without taking input from user in datetimepicker

                      Ondo