seqlua
view README @ 22:50c6388d4963
Added TODO to README: iterator triplet approach doesn't work
author | jbe |
---|---|
date | Thu Aug 21 13:04:45 2014 +0200 (2014-08-21) |
parents | 2fad7f50076b |
children | 29792283522f |
line source
1 seqlua: Extended sequences and iterators in Lua
2 ===============================================
4 This is an experimental package to extend Lua in the following manner:
6 * allow ipairs(...) to accept tables as well as functions or iterator triplets,
7 * provide a function iterator(...) that returns single functions unmodified,
8 but converts
9 * iterator triplets into closures, and
10 * tables into a function closure that iterates over the elements,
11 * provide the auxiliary C functions and macros to simplify iterating over both
12 tables and iterator functions with the same statement.
14 This library completely ignores the ``__ipairs`` metamethod (as it is
15 deprecated since Lua 5.3.0-alpha). It respects, however, any ``__index`` and
16 ``__call`` metamethods (this may cause unexpected behavior when passing
17 callable tables to ``ipairs``). The ``__call`` metamethod takes precedence over
18 an existing ``__index`` metamethod.
22 Lua part of the library
23 -----------------------
25 The new ``ipairs(...)`` function works as follows:
27 require "seqlua"
29 t = {"a", "b", "c"}
31 for i, v in ipairs(t) do
32 print(i, v)
33 end
34 -- prints:
35 -- 1 a
36 -- 2 b
37 -- 3 c
39 function alphabet()
40 local letter = nil
41 return function()
42 if letter == nil then
43 letter = "a"
44 elseif letter == "z" then
45 return nil
46 else
47 letter = string.char(string.byte(letter) + 1)
48 end
49 return letter
50 end
51 end
53 f = alphabet("a", "z")
55 for i, v in ipairs(f) do
56 print(i, v)
57 end
58 -- prints:
59 -- 1 a
60 -- 2 b
61 -- 3 c
62 -- ...
63 -- 25 y
64 -- 26 z
66 set = {apple = true, banana = true}
67 for i, k, v in ipairs(pairs(set)) do
68 print(i, k, v)
69 end
70 -- prints:
71 -- 1 banana true
72 -- 2 apple true
73 -- (order of "apple" and "banana" may vary)
75 More examples for invoking the ``ipairs(...)`` function can be found in the
76 file ``seqlua_ipairs_example.lua``.
78 The function ``iterator(...)`` may be used to convert any table, any function,
79 or any iterator triplet into a single function (possibly creating a closure):
81 require "seqlua"
83 function filter_strings(...)
84 nextvalue = iterator(...)
85 return function()
86 local value
87 repeat
88 value = nextvalue()
89 until value == nil or type(value) == "string"
90 return value
91 end
92 end
94 for i, v in ipairs(filter_strings{"Hello", true, "World"}) do
95 print(i, v)
96 end
97 -- prints:
98 -- 1 Hello
99 -- 2 World
101 tbl = {apple = true, banana = true, [1] = "array entry"}
102 for v in filter_strings(pairs(tbl)) do
103 print(v)
104 end
105 -- prints:
106 -- banana
107 -- apple
108 -- (order may vary)
112 C part of the library
113 ---------------------
115 In ``seqlualib.h``, the following macro is defined:
117 #define seqlua_iterloop(L, iter, idx) \
118 for ( \
119 seqlua_iterinit((L), (iter), (idx)); \
120 seqlua_iternext(iter); \
121 lua_pop((L), 1) \
122 )
124 This macro allows iteration over either tables or iterator functions (but not
125 iterator triplets) as the following example function demonstrates:
127 int printcsv(lua_State *L) {
128 seqlua_Iterator iter;
129 seqlua_iterloop(L, &iter, 1) {
130 if (seqlua_itercount(&iter) > 1) fputs(",", stdout);
131 fputs(luaL_tolstring(L, -1, NULL), stdout);
132 lua_pop(L, 1); // pops value that luaL_tolstring pushed onto stack
133 }
134 fputs("\n", stdout);
135 return 0;
136 }
138 printcsv{"a", "b", "c"}
139 -- prints: a,b,c
141 printcsv(assert(io.open("testfile")):lines())
142 -- prints: line1,line2,... of "testfile"
144 Additionally, ``seqlualib`` includes a function ``seqlua_iterclosure(L, idx)``,
145 which converts a table at a given stack index into a function closure (stored
146 on the same stack index) that iterates over the elements of the table. If the
147 value at the given stack index is already a function (or if it is callable
148 through a ``__call`` metamethod), then ``seqlua_iterclosure(L, idx)`` leaves
149 the value at ``idx`` unchanged.
152 TODO
153 ----
155 Accepting iterator triplets doesn't work, because even if a single function
156 is passed to ipairs, that function still might expect to get the previous
157 iteration value as second argument. Therefore, accepting iterator triplets
158 as argument to ipairs should be removed.