lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I played a bit with the new 'for' syntax.

I started with the 2002/06/06 mail from Roberto, giving pseudo-code. Since I
prefer long variable names, I rewrote it a bit for better (mine!)
comprehension.
Let me quote it here, as a reminder:

Pseudo code:

for var1, ..., varn in expList do
  block
end

is equivalent to

do
  local _func, _state, var1 = expList
  local var2, ..., varn
  while 1 do
    var1, ..., varn = _func(_state, var1)
    if var1 == nil then
      break
    end
    block
  end
end

so, if I understand correctly:
expList is a function which must return at least another function, and that
can return a state (for persistance of data) and an initial value.
_func, returned by expList, must return n values, the first being nil when
process is exhausted.

I tried with the following code (also provided by Roberto):
t = { "a", "b", "c" }
for i, k in nexti(t) do print(i, k) end
for k, v in next, t do print(k, v) end
for k, v in t do print(k, v) end
The results are identical. I am not sure to understand the second syntax
(with 'next').
It seems I cannot write "for k in next do ... end", Lua reports 'next' is
expecting a parameter, but which one it gets in the above line?

--

The code snippet given by Roberto to read the lines of a file helped me
understanding the pseudo-code above (I am a bit slow...).

It was:

function lines(filename)
  local f = assert(io.open(filename, "r"))
  return function ()
    return f:read() or (assert(f:close()) and nil), i
  end
end

for line in lines(file) do
  print(line) -- Or process line, etc.
end

It works fine, of course. I just don't understand the "and nil" part. Oh, I
suppose it is to force the return of a nil value, since assert doesn't return
anything.

I started to rewrite it like:

function lines(filename)
  local f = assert(io.open(filename, "r"))
  local i = 0
  return function ()
    i = i + 1
    return f:read() or (assert(f:close()) and nil), i
  end
end

local line, number
for line, number in lines(file) do
  print("(" .. number .. ") " .. line)
end

We already have a state persistance... I suppose this is the magic of 5.0's
closures, the 'i' in the anonymous function pointing to the local variable in
lines().

I made a final version, using state and initial value as per the
pseudo-code:

function lines(filename)
  local f = assert(io.open(filename, "r"))
  local state = {}
  state.persistentValue = " "
  state.counter = 0
  return function (_state, _previousValue)
    _state.persistentValue = "." .. _state.persistentValue
    _state.counter = _state.counter + 1
    print(_state.persistentValue .. _previousValue)
    return f:read() or (assert(f:close()) and nil), _state.counter
  end, state, "First value"
end

But I am no longer sure of the advantage of this state over the previous
version...
Well, it looks more like OO, and I am probably missing some side effect.

Sorry if my observations seem obvious to most of you, I though it could be
useful for those having some difficulties to grab these concepts.

Regards.

-- 
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--

GMX - Die Kommunikationsplattform im Internet.
http://www.gmx.net