rev |
line source |
jbe@0
|
1 seqlua: Extended sequences and iterators in Lua
|
jbe@0
|
2 ===============================================
|
jbe@0
|
3
|
jbe@0
|
4 This is an experimental package to extend Lua in the following manner:
|
jbe@0
|
5
|
jbe@23
|
6 * allow ipairs(...) to accept tables as well as functions
|
jbe@23
|
7 * provide auxiliary C functions and macros to simplify iterating over both
|
jbe@0
|
8 tables and iterator functions with the same statement.
|
jbe@0
|
9
|
jbe@0
|
10 This library completely ignores the ``__ipairs`` metamethod (as it is
|
jbe@18
|
11 deprecated since Lua 5.3.0-alpha). It respects, however, any ``__index`` and
|
jbe@18
|
12 ``__call`` metamethods (this may cause unexpected behavior when passing
|
jbe@18
|
13 callable tables to ``ipairs``). The ``__call`` metamethod takes precedence over
|
jbe@18
|
14 an existing ``__index`` metamethod.
|
jbe@0
|
15
|
jbe@0
|
16
|
jbe@0
|
17
|
jbe@0
|
18 Lua part of the library
|
jbe@0
|
19 -----------------------
|
jbe@0
|
20
|
jbe@0
|
21 The new ``ipairs(...)`` function works as follows:
|
jbe@0
|
22
|
jbe@0
|
23 require "seqlua"
|
jbe@0
|
24
|
jbe@0
|
25 t = {"a", "b", "c"}
|
jbe@0
|
26
|
jbe@0
|
27 for i, v in ipairs(t) do
|
jbe@0
|
28 print(i, v)
|
jbe@0
|
29 end
|
jbe@0
|
30 -- prints:
|
jbe@0
|
31 -- 1 a
|
jbe@0
|
32 -- 2 b
|
jbe@0
|
33 -- 3 c
|
jbe@0
|
34
|
jbe@19
|
35 function alphabet()
|
jbe@0
|
36 local letter = nil
|
jbe@0
|
37 return function()
|
jbe@0
|
38 if letter == nil then
|
jbe@19
|
39 letter = "a"
|
jbe@19
|
40 elseif letter == "z" then
|
jbe@0
|
41 return nil
|
jbe@0
|
42 else
|
jbe@0
|
43 letter = string.char(string.byte(letter) + 1)
|
jbe@0
|
44 end
|
jbe@0
|
45 return letter
|
jbe@0
|
46 end
|
jbe@0
|
47 end
|
jbe@0
|
48
|
jbe@23
|
49 for i, v in ipairs(alphabet()) do
|
jbe@0
|
50 print(i, v)
|
jbe@0
|
51 end
|
jbe@0
|
52 -- prints:
|
jbe@0
|
53 -- 1 a
|
jbe@0
|
54 -- 2 b
|
jbe@0
|
55 -- 3 c
|
jbe@0
|
56 -- ...
|
jbe@0
|
57 -- 25 y
|
jbe@0
|
58 -- 26 z
|
jbe@0
|
59
|
jbe@23
|
60 function filter(f, seq)
|
jbe@23
|
61 return coroutine.wrap(function()
|
jbe@23
|
62 for i, v in ipairs(seq) do f(v) end
|
jbe@23
|
63 end)
|
jbe@0
|
64 end
|
jbe@19
|
65
|
jbe@23
|
66 function filterfunc(v)
|
jbe@23
|
67 local type_v = type(v)
|
jbe@23
|
68 if type_v == "string" then
|
jbe@23
|
69 coroutine.yield(v)
|
jbe@23
|
70 elseif type_v == "number" then
|
jbe@23
|
71 for i = 1, v do
|
jbe@23
|
72 coroutine.yield(true)
|
jbe@23
|
73 end
|
jbe@0
|
74 end
|
jbe@0
|
75 end
|
jbe@0
|
76
|
jbe@23
|
77 for v in filter(filterfunc, {"a", "b", 3, "c"}) do
|
jbe@0
|
78 print(v)
|
jbe@0
|
79 end
|
jbe@0
|
80 -- prints:
|
jbe@23
|
81 -- a
|
jbe@23
|
82 -- b
|
jbe@23
|
83 -- true
|
jbe@23
|
84 -- true
|
jbe@23
|
85 -- true
|
jbe@23
|
86 -- c
|
jbe@0
|
87
|
jbe@0
|
88
|
jbe@0
|
89 C part of the library
|
jbe@0
|
90 ---------------------
|
jbe@0
|
91
|
jbe@0
|
92 In ``seqlualib.h``, the following macro is defined:
|
jbe@0
|
93
|
jbe@0
|
94 #define seqlua_iterloop(L, iter, idx) \
|
jbe@0
|
95 for ( \
|
jbe@0
|
96 seqlua_iterinit((L), (iter), (idx)); \
|
jbe@0
|
97 seqlua_iternext(iter); \
|
jbe@0
|
98 lua_pop((L), 1) \
|
jbe@0
|
99 )
|
jbe@0
|
100
|
jbe@23
|
101 This macro allows iteration over either tables or iterator functions as the
|
jbe@23
|
102 following example function demonstrates:
|
jbe@0
|
103
|
jbe@0
|
104 int printcsv(lua_State *L) {
|
jbe@0
|
105 seqlua_Iterator iter;
|
jbe@0
|
106 seqlua_iterloop(L, &iter, 1) {
|
jbe@0
|
107 if (seqlua_itercount(&iter) > 1) fputs(",", stdout);
|
jbe@0
|
108 fputs(luaL_tolstring(L, -1, NULL), stdout);
|
jbe@1
|
109 lua_pop(L, 1); // pops value that luaL_tolstring pushed onto stack
|
jbe@0
|
110 }
|
jbe@0
|
111 fputs("\n", stdout);
|
jbe@0
|
112 return 0;
|
jbe@0
|
113 }
|
jbe@0
|
114
|
jbe@11
|
115 printcsv{"a", "b", "c"}
|
jbe@11
|
116 -- prints: a,b,c
|
jbe@11
|
117
|
jbe@11
|
118 printcsv(assert(io.open("testfile")):lines())
|
jbe@11
|
119 -- prints: line1,line2,... of "testfile"
|
jbe@0
|
120
|
jbe@0
|
121
|