Using timer.simple inside a k,v in pairs loop?

Hey guys.

This is what I’m trying to test:

[lua]for k,v in pairs(player.Getall()) do
timer.Simple(1, function() v:DoSomething() end)

Here’s the problem: when the timer actually runs after a second, if there was more than one value in the k,v table, then it doesn’t know which “v” to use.

Is there any way to overcome this? You can’t store v as something because it’s a pointer…

Have you tested this? It should work fine.

Rather than starting x timers you should rather put the loop IN the timer callback.

Yes, I have tested this. It gets an error saying V is null, in other words, it either got to the end of the table or v doesn’t exist anymore because the loop is over long before a second has passed.

But I know what you mean, you’d think the entity gets passed into the timer function.

That’s not how this works. The anonymous function you pass to the timer is a closure with v as an upvalue, therefore v (in the closure) will not become nil until the closure is destroyed.

[editline]5th June 2013[/editline]

In other words: it doesn’t matter if the loop has ended before the timer is run. The loop just creates closures and passes them to the timer - it doesn’t need to be alive for the upvalue to remain non-nil.

Its important not to confuse nil with null.

You get errors with null, if the entity you stored the reference to (value v) has dissapeared for whatever reason. ( In your case a player could disconnect, before the timer runs )

So, you should check if the entity is still valid, before doing anything.

Why isnt All capitalised in player.Getall it should be player.GetAll()
(doubt thats actually your problem, but if thats the exact code you are testing with it would be a problem)

No, I wrote it just now. The actual code is way, way bigger.

However, putting the loops inside the timers, not the other way around, fixes this.

Is there a possibility the player left in this timescape? ( perhaps, in the actual version the timer’s much longer? )

None the less, it’s always nice to do something like this :

for k, v in pairs( player.GetAll() ) do

timer.Simple( 5, function()

	if ( v && IsValid( v ) ) then 





for k,v in pairs(player.GetAll()) do
local v = v
timer.Simple(5, function() v:DoSomething() end)
I think you should do it this way.

By the way, IsValid() already checks if v exists.

v already is a local variable.


timer.Simple(1, function()
for _, v in pairs(player.GetAll()) do

Finally someone did it right ._.