Iterating Tables & Closures
02/09/21 08:09 Filed in: Lua
Last time I learned about tables, the only real data structure in Lua. I'm going to cover a few more items related to them.
Pairs and Ipairs
One of the first things I did when I learned about Lua tables was try to iterate over them the way I iterate over dictionaries in other languages.
Well, that didn't work: "attempt to call a table value", yes, I know. I'm trying to iterate over a table. What's wrong with that? This should work. The error message isn't very helpful. [Aside: I really wish error messages actually told you how to fix the problem, not just give you an obtuse string.]
I think there is a clue in the error message: "value". I'm trying to iterate over a table, not something Lua considers a table value. What's the value of a table? Being curious, I tried using what little I already know about Lua:
Ha! That explains it, I think. As I already know, nums is a table, but printing it dumps what looks like the memory address of the table. So in my test for loop above, I'm trying to iterate over the memory address of the table, not a table. That's my interpretation of what is happening.
I'm a smart dude. I'm a programmer. I know what to do. I just dereference the address with an * to get the value.
I'm not as smart as I think. That doesn't work in Lua. Grumble…grumble. I have no idea. Time to search. I find examples that use a function called pairs that returns individual keys and values. Let's try that.
Interesting. Remember, nums is an array, not a dictionary so it's returning the index as the k (key). A quick tests shows me I can just use:
for v in pairs(nums) do
But I don't know if that actually returns the key or the value since they are the same. Another quick test shows me how to get the values I want.
I have to use the blank operator _ . That makes sense to me.
In the examples I saw, there was something called ipairs, that said it was used to iterate over arrays. From what I can see it works exactly the same way as pairs. I have no idea why there are two keywords for the same thing. I'm sure there are internal differences, but do I really care at this point? No. I'll just use pairs since it can iterate over any kind of table, be it a dictionary or array as I just showed. As William James once said, "A difference which makes no difference is no difference at all."
Closures
Lua supports closures which are first class functions that can return anonymous functions and capture the state of a chunk/block. Here is a simple example that creates and returns an anonymous adder function that is then used.
This prints 2 and 28. The important part to understand are lines 2 through 4. This is chunk that returns a function and expects a single parameter as input, cleverly called input here. The returned anonymous function, in turn, returns the sum of the two numbers. Line 7 invokes adder with a parameter of 1. Adder returns a function which takes a parameter and will add that parameter to the passed in number (1) to the outer adder function. We assign the created anonymous function to the variable add1. We do that same thing with the number 7 on line 8. We can then call these generated functions normally on lines 10 and 11.
Digging into various papers and docs, it seems that all Lua functions are actually anonymous functions with some syntactic-sugar.
function myFunc(x)
end
Is equivalent to and implemented as:
myFunc = function(x)
end
That's enough for today. There is more to Lua tables from what I've seen, so I'll cover more next time.