3

I want to refer to an integer, but the reference should be inside a table. The goal is an automatic string formatting function, which is updating the values every frame.

>> num = 5
>> table = {}
>> table[1] = num
>> num = 10
>> print(table[1])
>> 5

If i run this the value num is only getting copied, but i need a reference instead. I am writing a game with the lua löve2D library at the moment. Here is an excerpt of my code:

function StringDrawSystem:draw()
    for index, entity in pairs(self.targets) do
        local str = entity:getComponent("StringComponent")
        love.graphics.setFont(str.font)
        local position = entity:getComponent("PositionComponent")
        love.graphics.print(string.format(str.string, unpack(str.values)), position.x, position.y)
    end
end

str.values is a table that should contain the references to the wanted values. Those values are not necessarily global.

entity:getComponent("StringComponent") -- is equal to 
entity.components.StringComponent -- StringComponent is just 
                                  -- a component added to the entity 

StringComponent is a simple class with 3 fields.

StringComponent = class("StringComponent")

function StringComponent:__init(font, string, values) 
    self.font = font
    self.string = string
    self.values = values
end
3
  • Any solution you come up with will have to involve using either tables or userdata because those are the only two types in lua that have any notion of mutable reference semantics. Commented Sep 16, 2013 at 0:44
  • Is entity:getComponent the function responsible for setting up str.values's table? Commented Sep 16, 2013 at 0:53
  • 1
    You may be able to setup str.values so it triggers a __index and have the metamethod build up the table of values to return on-the-fly. But you still need to know where to get those values from -- probably do this via an upvalue like Colonel showed. I can give a more concrete example if you show how str.values is being setup. Commented Sep 16, 2013 at 0:59

3 Answers 3

2

You can't do it without one more level of redirection, as you can't have references to numerics values. You can store the value you need in a table and modify the first element in that table:

num = {}
num[1] = 5
table = {}
table[1] = num
num[1] = 10
print(table[1][1])
-- 10
Sign up to request clarification or add additional context in comments.

1 Comment

So i have to reference tables. Thanks for your advise.
2

You can't do this directly, but you can instead provide a closure to call when you need the string value, like this:

x = 5
table = {}

table["key"] = function() return x end

print(table["key"]()) -- Will print 5
x = 10
print(table["key"]()) -- Will print 10

3 Comments

The main problem on this solution is that i would have to hardcode a function for every value i want to print. But the values i want to print are produced by different systems and the main engine that is managing my entitysystem. Those values are somewhere inside that engine and not predictable, but i can read them at certain points. At this points i want to put them inside the table to have a steady dynamically generated reference to print those values.
Then no, you can't do that. This isn't C. You should think about rethinking your approach if you are having to do this.
No, it won't print 10!
0

I found a solution for my current problem. Every int i want to reference is in some kind of way a child of another table. So, for example, if you want to refer to table.int and table2.int2 i pass {{table, "int"}, {table2, "int2"}} to values in the StringComponent's constructor. Now you are able to create a table with the updated values by using

local val = {}
for k, v in pairs(str.values) do
    table.insert(val, v[1][v[2]])
end

Now i am able to format the string with

string.format(str.string, unpack(val))

If you have a better solution, feel free to post it, so i can optimize my code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.