seqlua

annotate README @ 18:431fa6946a61

Precedence of __call and __index noted in README
author jbe
date Wed Aug 20 06:47:14 2014 +0200 (2014-08-20)
parents a95fbd16473f
children 2fad7f50076b
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@0 6 * allow ipairs(...) to accept tables as well as functions or iterator triplets,
jbe@0 7 * provide a function iterator(...) that returns single functions unmodified,
jbe@0 8 but converts
jbe@0 9 * iterator triplets into closures, and
jbe@0 10 * tables into a function closure that iterates over the elements,
jbe@0 11 * provide the auxiliary C functions and macros to simplify iterating over both
jbe@0 12 tables and iterator functions with the same statement.
jbe@0 13
jbe@0 14 This library completely ignores the ``__ipairs`` metamethod (as it is
jbe@18 15 deprecated since Lua 5.3.0-alpha). It respects, however, any ``__index`` and
jbe@18 16 ``__call`` metamethods (this may cause unexpected behavior when passing
jbe@18 17 callable tables to ``ipairs``). The ``__call`` metamethod takes precedence over
jbe@18 18 an existing ``__index`` metamethod.
jbe@0 19
jbe@0 20
jbe@0 21
jbe@0 22 Lua part of the library
jbe@0 23 -----------------------
jbe@0 24
jbe@0 25 The new ``ipairs(...)`` function works as follows:
jbe@0 26
jbe@0 27 require "seqlua"
jbe@0 28
jbe@0 29 t = {"a", "b", "c"}
jbe@0 30
jbe@0 31 for i, v in ipairs(t) do
jbe@0 32 print(i, v)
jbe@0 33 end
jbe@0 34 -- prints:
jbe@0 35 -- 1 a
jbe@0 36 -- 2 b
jbe@0 37 -- 3 c
jbe@0 38
jbe@8 39 function alphabet(from, to)
jbe@0 40 local letter = nil
jbe@0 41 return function()
jbe@0 42 if letter == nil then
jbe@8 43 letter = from
jbe@8 44 elseif letter == to then
jbe@0 45 return nil
jbe@0 46 else
jbe@0 47 letter = string.char(string.byte(letter) + 1)
jbe@0 48 end
jbe@0 49 return letter
jbe@0 50 end
jbe@0 51 end
jbe@0 52
jbe@8 53 f = alphabet("a", "z")
jbe@0 54
jbe@0 55 for i, v in ipairs(f) do
jbe@0 56 print(i, v)
jbe@0 57 end
jbe@0 58 -- prints:
jbe@0 59 -- 1 a
jbe@0 60 -- 2 b
jbe@0 61 -- 3 c
jbe@0 62 -- ...
jbe@0 63 -- 25 y
jbe@0 64 -- 26 z
jbe@0 65
jbe@8 66 c = setmetatable(
jbe@8 67 { iter = alphabet("a", "f") },
jbe@8 68 { __call = function(t) return t.iter() end }
jbe@8 69 )
jbe@8 70
jbe@8 71 for i, v in ipairs(c) do
jbe@8 72 print(i, v)
jbe@8 73 end
jbe@8 74 -- prints:
jbe@8 75 -- 1 a
jbe@8 76 -- 2 b
jbe@8 77 -- 3 c
jbe@10 78 -- 4 d
jbe@10 79 -- 5 e
jbe@10 80 -- 6 f
jbe@8 81
jbe@13 82 g = coroutine.wrap(function()
jbe@12 83 coroutine.yield("Alice")
jbe@12 84 coroutine.yield("Bob")
jbe@12 85 for i = 1, 3 do
jbe@12 86 coroutine.yield("Person #" .. tostring(i))
jbe@12 87 end
jbe@13 88 end)
jbe@12 89
jbe@13 90 for i, v in ipairs(g) do
jbe@12 91 print(i, v)
jbe@12 92 end
jbe@12 93 -- prints:
jbe@12 94 -- 1 Alice
jbe@12 95 -- 2 Bob
jbe@12 96 -- 3 Person #1
jbe@12 97 -- 4 Person #2
jbe@12 98 -- 5 Person #3
jbe@12 99
jbe@0 100 set = {apple = true, banana = true}
jbe@0 101 for i, k, v in ipairs(pairs(set)) do
jbe@0 102 print(i, k, v)
jbe@0 103 end
jbe@0 104 -- prints:
jbe@0 105 -- 1 banana true
jbe@0 106 -- 2 apple true
jbe@0 107 -- (order of "apple" and "banana" may vary)
jbe@0 108
jbe@0 109 The function ``iterator(...)`` may be used to convert any table, any function,
jbe@0 110 or any iterator triplet into a single function (possibly creating a closure):
jbe@0 111
jbe@2 112 require "seqlua"
jbe@2 113
jbe@0 114 function filter_strings(...)
jbe@0 115 nextvalue = iterator(...)
jbe@0 116 return function()
jbe@0 117 local value
jbe@0 118 repeat
jbe@0 119 value = nextvalue()
jbe@0 120 until value == nil or type(value) == "string"
jbe@0 121 return value
jbe@0 122 end
jbe@0 123 end
jbe@0 124
jbe@0 125 for i, v in ipairs(filter_strings{"Hello", true, "World"}) do
jbe@0 126 print(i, v)
jbe@0 127 end
jbe@0 128 -- prints:
jbe@0 129 -- 1 Hello
jbe@0 130 -- 2 World
jbe@0 131
jbe@0 132 tbl = {apple = true, banana = true, [1] = "array entry"}
jbe@0 133 for v in filter_strings(pairs(tbl)) do
jbe@0 134 print(v)
jbe@0 135 end
jbe@0 136 -- prints:
jbe@0 137 -- banana
jbe@0 138 -- apple
jbe@0 139 -- (order may vary)
jbe@0 140
jbe@0 141
jbe@0 142
jbe@0 143 C part of the library
jbe@0 144 ---------------------
jbe@0 145
jbe@0 146 In ``seqlualib.h``, the following macro is defined:
jbe@0 147
jbe@0 148 #define seqlua_iterloop(L, iter, idx) \
jbe@0 149 for ( \
jbe@0 150 seqlua_iterinit((L), (iter), (idx)); \
jbe@0 151 seqlua_iternext(iter); \
jbe@0 152 lua_pop((L), 1) \
jbe@0 153 )
jbe@0 154
jbe@0 155 This macro allows iteration over either tables or iterator functions (but not
jbe@0 156 iterator triplets) as the following example function demonstrates:
jbe@0 157
jbe@0 158 int printcsv(lua_State *L) {
jbe@0 159 seqlua_Iterator iter;
jbe@0 160 seqlua_iterloop(L, &iter, 1) {
jbe@0 161 if (seqlua_itercount(&iter) > 1) fputs(",", stdout);
jbe@0 162 fputs(luaL_tolstring(L, -1, NULL), stdout);
jbe@1 163 lua_pop(L, 1); // pops value that luaL_tolstring pushed onto stack
jbe@0 164 }
jbe@0 165 fputs("\n", stdout);
jbe@0 166 return 0;
jbe@0 167 }
jbe@0 168
jbe@11 169 printcsv{"a", "b", "c"}
jbe@11 170 -- prints: a,b,c
jbe@11 171
jbe@11 172 printcsv(assert(io.open("testfile")):lines())
jbe@11 173 -- prints: line1,line2,... of "testfile"
jbe@0 174
jbe@0 175 Additionally, ``seqlualib`` includes a function ``seqlua_iterclosure(L, idx)``,
jbe@0 176 which converts a table at a given stack index into a function closure (stored
jbe@0 177 on the same stack index) that iterates over the elements of the table. If the
jbe@15 178 value at the given stack index is already a function (or if it is callable
jbe@15 179 through a ``__call`` metamethod), then ``seqlua_iterclosure(L, idx)`` leaves
jbe@15 180 the value at ``idx`` unchanged.
jbe@0 181
jbe@0 182

Impressum / About Us