[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Abusing Lua iterators for fun and profit
- From: Dirk Laurie <dirk.laurie@...>
- Date: Fri, 6 Feb 2015 08:22:50 +0200
2015-02-06 2:00 GMT+02:00 Sean Conner <sean@conman.org>:
> It was thus said that the Great Soni L. once stated:
>>
>> > It's (in my opinion) cleaner and easier to read. Now my question: can
>> > I rely upon this behavior of io.lines() and string.gmatch() to only
>> > return a single function? I tested it on Lua 5.1, 5.2, 5.3 and LuaJIT,
>> > and in each case, only a function was returned. Am I relying upon an
>> > implementation detail? Should I use the first version, where I pass in
>> > the state and value each time, to be "safe"?
>> >
>> According to the manual:
>> http://www.lua.org/manual/5.3/manual.html#pdf-string.gmatch
>>
>> "Returns an *iterator function*"
>>
>> I believe it is safe to assume "iterator function" means it returns only
>> a function that returns the next match or nil at the end. (If it said
>> just "an iterator", THEN it wouldn't be safe to assume so)
>
> I think Roberto will have to chime in here because of replies from
> Daurnimator:
>
>> Yes. this is an implementation detail. please do not rely on it. It just
>> happens to be that state and 'var_1' are nil
>>
>> IIRC this caught out a few people/modules when run under alternate
>> implementations (was it Kahlua?)
>
> and Roberto:
>
>> I guess the best solution is not to use lines/gmatch at all, but
>> read/match (or find). See [1] for something similar.
>>
>> [1] http://www.lua.org/pil/7.1.html
>
> Either it's documented that io.lines() (and a few others) only return a
> function, or the manual may need some clarification.
One must distinguish between an "iterator function" and an
"iterator factory".
io.lines(...), string.gmatch(str,pat) are iterator functions
io.lines, string.gmatch are iterator factories
An iterator takes two arguments, the first of which is guaranteed
always to be the same, and returns as many values as you like,
only the first of which affects progress of the iteration.
An iterator factory takes as many arguments as you like and
can usefully return up to three values. The second value, if
any, will be the invariant; the third value, if any, will be the
initial value to the generic `for`.
In my opinion, if an iterator function returns more than one
value, that behaviour should be explicitly documented, since
it relies on a gotcha: something that lexically looks like one
item, but may be more. It's clever, no doubt about that, since
it can be thought of as providing default values that you can
always discard by using parentheses, but it is too clever by
half for my taste.
io.lines and string.gmatch don't do that, so there is no need
to say anything about it.