For loops

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

This might also be of some help: http://www.lua.org/manual/5.1/manual.html#2.4.5

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 :slight_smile:

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 :slight_smile:

Wow thanks guys that did it for me