Exercise on Closures

Trace the following code in a debugger

  • 1. Determine how name and ages are used in each function
  • 2. Discuss and explain to the group
local names = {'Carol', 'Jess', 'John', 'Daniel' }
local ages = {Carol = 20, Jess = 14, John = 41, Daniel = 63}

table.sort(names, function (name1, name2)
  return ages[name1] > ages[name2]  -- ages is an upvalue here, can be seen
end)

for i = 1, #names do
  print(names[i])
end

names = {'Barbara', 'Ben', 'Harry', 'Jen' }
ages = {Barbara = 20, Ben = 14, Harry = 41, Jen = 63}

function sortByAge (names, ages) -- references names and ages are local to sort
  table.sort(names,function (name1, name2) -- names and ages can be seen within sort
    return ages[name1] > ages[name2] -- ages can be seen within anonymous function
  end)
end
sortByAge(names, ages)
print("\n\n\n")
for i = 1, #names do
  print(names[i])
end

names = {'Barbara', 'Ben', 'Harry', 'Jen' }
ages = {Barbara = 20, Ben = 14, Harry = 41, Jen = 63}

function sortByAge () -- call has two parameters neither of which are used
  function ageCompare(name1, name2) -- ages and names are upvalues here
    return ages[name1] > ages[name2] -- ages can be seen within ageCompare
  end
  table.sort(names,ageCompare)  -- references names and ages can be seen within sortByAge
end
sortByAge(names, ages)  -- passed in names and ages in the call but they are not used
print("\n\n\n")
for i = 1, #names do
  print(names[i])
end
```

*   In the examples the ages variable within the function is called a non-local variable

    *   It is not global and it is not local

    *   This is sometimes referred to as an upvalue

    *   It can be seen because of the scoping rules of Lua

_Closure definition_ - A closure is a function plus all that it needs to access non-local variables correctly

Trace through the following code using the debugger

*   1\. Determine how the closures work

*   2\. Explain and discuss

function counter ()
  local i = 0;
  return function ()
    i = i + 1
    return i
  end
end

theCounter = counter()
print(theCounter()) -- the function reference continues to refer to the same function
print(theCounter()) -- and its local variables (including its parameters)

-- iterators and closure

function iterator(theList)
  local i = 0
  return (function () i = i + 1; return theList[i] end)
end

local numbers = {"Earth","Mars","Saturn","Venus"}
iter = iterator(numbers) -- get a reference to the function
while true do
  local theItem = iter() -- use the function
  if theItem == nil then break end
  print (theItem)
end
```

</pre>