Yes i am having a problem with the for loop, not because it’s giving me a problem with the compiler/interpreter but because I don’t understand it "woe to you ".."who do not understand the for loop."
I’m fine with the numerical version but the generic version eh I don’t understand it at all. Could someone explain it to me as if you were explaing to a child or as simple as possible thanks
For loops are a way of repeating a command, or series of commands. In Codea, they have the following structure
for x=startValue, endValue do
-- the stuff you want repeated
end
x is a counter parameter and can be used to track how many times you have been round the loop. The number of times the loop code is repeated will be the difference between the startValue and endValue parameter. In the simplest case x is an integer and increases by one each time starting from the startValue until the point where adding one to x would make it bigger than the end value.
For example
for x=1,10 do
print(x)
end
Will print out the numbers, 1 to 10
Similarly,
for x=5,8 do
print(x)
end
Will print the numbers 5 through to 8
That’s all there is to it. In more complex cases you can set the increment size of x to something other than one, including negative numbers to get a count downward. This can also be done using
for x=1,10 do
print(11-x)
end
Sorry West i think mightn’t have phrased the question suitably enough, i was asking how the generic
for loop worked thanks in advanced.
Oh, OK. Do you mean looping through a table?
Have you seen this example from the documentation?
(https://bitbucket.org/TwoLivesLeft/codea/wiki/Documentation)
This example uses the ipairs function to sequentially iterate over a table. Note that ipairs only works on tables that have sequential elements beginning at 1.
-- Iterate over an array named 'arr' arr = { 3, 2, 1 }
for i,v in ipairs(arr) do
print( "arr["..i.."] = "..v )
end
Prints:
arr[1] = 3
arr[2] = 2
arr[3] = 1
This example uses pairs to iterate over all the key/value pairs in a table, unlike ipairs the keys do not have to be integral values, and can be anything.
-- Iterate over a table named 'tab'
tab = { x = 3, y = "string", z = 1 }
for key,value in pairs(tab) do
print( "tab."..key.." = "..value )
end
Prints:
tab.y = string
tab.x = 3
tab.z = 1
Hello @Dalorbi. This is my attempt at an explanation for a child:
Let us start with a Lua table. A Lua table can be empty. If it is not, it is a collection of one or more entries.
Each entry is a pair of values. The order of the pair matters: the pair “black”, “cat” is not the same as the pair “cat”, “black”.
The first value of the pair allows you to look up an entry in the table. We can call it the ‘index’ (like the index of a book) or a ‘key’ (like a key to a map).
Keys are usually whole numbers or strings, but they do not have to be.
The second value of the pair can be anything that is not a nil value.
It would be useful to be able to get each entry in a table, in turn, and do something with the key or its associated value. That is what the generic for
allows you to do. It looks like this:
for key, value in pairs(myTable) do
print ("The key is", key)
print (".. and its associated value is", value)
end
In the example above, for each entry in the table myTable
, in turn, key
is set to the key value and value
is set to the second value in the pair. All the entries in the table are then looped through, but in no particular order.
Often some or all of the keys in a particular table are the whole numbers 1, 2, 3 and so on. A different form of the generic for
allows you to loop through those sorts of keys in order, until there is a gap in the sequence of keys:
for key, value in ipairs(myTable) do
print ("The whole number key is", key)
print (".. and its associated value is", value)
end
The variables key
and value
only exist inside the loop. Once the for
loop has done its work, it is as if they never existed.
I might add that pairs()
and ipairs()
are functions provided by Lua for looping through entries in tables, but it is possible to write other functions that allow a generic for
to loop through other things. For example, prime numbers:
--
-- Generic for
--
function setup()
for p in primes(100) do
print(p)
end
end
function primes(max)
local iterator = function (max, last)
local start, next
if last == 2 then start = 3 else start = last + 2 end
for i = start, max, 2 do
local isPrime = true
for j = 2, math.floor(math.sqrt(i)) do
if i % j == 0 then isPrime = false; break end
end
if isPrime then next = i; break end
end
return next
end
return iterator, max, 0
end
function draw()
background(0)
end
@mpilgrem: I was just about to say something similar, but you beat me to it while I was writing an example program to demonstrate. I’ll still include it just for completeness. Basically, there is nothing terribly special about pairs() and ipairs(). They can easily be implemented in Lua itself:
local function iter(t, i)
i = i + 1
local v = t[i]
if v then
return i, v
end
end
local function ipairs(t)
return iter, t, 0
end
local function pairs(t)
-- next is a built-in table iterator function
return next, t, nil
end
In fact, you don’t even need them to use the generic for statement to iterate over a table at all! They are there for convenience. Here’s how you could do it using a raw expression list, instead of pairs() and ipairs():
-- use iterator function declared above to
-- iterate over the numeric indices in a table
-- instead of using ipairs()
for i, v in iter, t, 0 do
print(i..":"..v)
end
-- use built-in iterator function next()
-- to iterate over all elements in a table
-- instead of using pairs()
for k, v in next, t, nil do
print(k..":"..v)
end
So you might have noticed that basically, the expression list in the generic for statement is an iterator function, an invariant (in this case a table), and a control variable. pairs() and ipairs() conveniently return the expression list expected by the generic for loop.
Edit: Here’s another example of an iterator for the generic for loop that iterates over all of the characters in a string:
function allChars(str)
local function strIter(s, i)
if i == string.len(s)then
return nil
end
i = i + 1
return i, string.sub(s, i, i)
end
return strIter, str, 0
end
local s = "Hello world!"
for i, c in allChars(s) do
print(i..":"..c)
end
And just in case we didn’t beat this dead horse enough, here is Roberto Ierusalimschy’s explaination from his book, Programming in Lua:
4.3.5 – Generic for
The generic for loop allows you to traverse all values returned by an iterator function. We have already seen examples of the generic for:
-- print all values of array `a'
for i,v in ipairs(a) do print(v) end
For each step in that code, i gets an index, while v gets the value associated with that index. A similar example shows how we traverse all keys of a table:
-- print all keys of table `t'
for k in pairs(t) do print(k) end
Despite its apparent simplicity, the generic for is powerful. With proper iterators, we can traverse almost anything, and do it in a readable fashion. The standard libraries provide several iterators, which allow us to iterate over the lines of a file (io.lines), the pairs in a table (pairs), the words of a string (string.gfind, which we will see in Chapter 20), and so on. Of course, we can write our own iterators. Although the use of the generic for is easy, the task of writing iterator functions has its subtleties. We will cover this topic later, in Chapter 7.
The generic loop shares two properties with the numeric loop: The loop variables are local to the loop body and you should never assign any value to the loop variables.
Let us see a more concrete example of the use of a generic for. Suppose you have a table with the names of the days of the week:
days = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"}
Now you want to translate a name into its position in the week. You can search the table, looking for the given name. Frequently, however, a more efficient approach in Lua is to build a reverse table, say revDays, that has the names as indices and the numbers as values. That table would look like this:
revDays = {["Sunday"] = 1, ["Monday"] = 2,
["Tuesday"] = 3, ["Wednesday"] = 4,
["Thursday"] = 5, ["Friday"] = 6,
["Saturday"] = 7}
Then, all you have to do to find the order of a name is to index this reverse table:
x = "Tuesday"
print(revDays[x]) --> 3
Of course, we do not need to manually declare the reverse table. We can build it automatically from the original one:
revDays = {}
for i,v in ipairs(days) do
revDays[v] = i
end
The loop will do the assignment for each element of days, with the variable i getting the index (1, 2, …) and v the value (“Sunday”, “Monday”, …).
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved.
and one more
The generic for function is described in the lua manual like so:
A for statement like
for var_1, ···, var_n in explist do block end
is equivalent to the code:
do
local f, s, var = explist
while true do
local var_1, ···, var_n = f(s, var)
var = var_1
if var == nil then break end
block
end
end
This looks quite cryptic. It breaks down like this: the explist (which is usually a function, like pairs()) returns 3 values, the first is the actual iterator function, the second is the data, oder which to iterate and the third is the iteration state. Note that in this state, the second and third value is optional, meaning that the explist only really needs to return the iterator function. A live example:
> =pairs({})
function: 0xa00f9e8 table: 0xa025450 nil
> =ipairs({})
function: 0xa010008 table: 0xa025698 0
>
Note how noth functions return a function (the iterator) as their first return value, the table being iterated as the second return value, and an initial value for the iteration as the third return value. For ipairs() this is the number 0, for pairs() this is an empty key.
Now, for each loop, the iterator function is called with the data returned as the second value and an iterator state as arguments. Note, that the iterator function may return any number of arguments, but the first returned value is always the iterator state for the next loop. Example:
> f, s, a = ipairs({1,4,9})
> =f,s,a
function: 0xa010008 table: 0xa025970 0
> =f(s, a)
1 1
> =f(s, 1)
2 4
> return f(s, 2)
3 9
> return f(s, 3)
>
There, I did what for does, I got the iterator function f, the data s, and the initial state a from the ipairs() function and then repeatedly called f with s and the first returned value from the last call (initializing with a, of course). The iterator function returned by ipairs() always returns the current index and the value stored at that index. When the iterator function returns nil as its first return value, then the for loop stops. There are a few examples for iterator functions above, for example in @toadkick’s reply.
Important is, there are only 2 things that are really needed for the for statement to work with this, which is 1. the iterator function, and 2. that for terminates when the iterator function returns nil. So you can also go ahead and write other iterators that store their state in their environment, a.k.a. closures. Check @toadkick’s implementation of ipairs() above. This is basically textbook, meaning, implemented as the spec sais it is. You could also do this:
function ipairs(t)
local idx = 0
return function()
idx = idx + 1
if t[idx] ~= nil then
return idx, t[idx]
else
return nil
end
end
end
same result, but storing its state in a closure. Still, the returned iterator function gets called with 2 arguments, like above, just that the first argument, being the second - empty - return value from this ipairs implementation, is always nil, and the seco0nd argument starts out as nil instead of 0 above, but then also counts through 1, 2, 3, and so on.
For additional experimentation, try manually going through the pairs() iterator, like I did above with ipairs(), and see how that goes. Generic for is quite easy, once you get the hang of it
Wow thanks guys that did it for me