seqlua

annotate README @ 30:367fc70acc15

Respect the __ipairs and __len metamethods
author jbe
date Sat Aug 23 23:13:17 2014 +0200 (2014-08-23)
parents 2c4d9e44f704
children 4fc9090ada1d
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@30 6 * allow ``ipairs(seq)`` to accept tables as well as functions (i.e function
jbe@30 7 iterators),
jbe@25 8 * add a new function ``string.concat(separator, seq)`` to concat either table
jbe@25 9 entries or function return values,
jbe@23 10 * provide auxiliary C functions and macros to simplify iterating over both
jbe@0 11 tables and iterator functions with the same statement.
jbe@0 12
jbe@30 13 In all cases, existing ``__index``, ``__len``, or ``__ipairs`` metamethods are
jbe@30 14 respected. The ``__ipairs`` metamethod takes precedence.
jbe@0 15
jbe@0 16
jbe@0 17 Lua part of the library
jbe@0 18 -----------------------
jbe@0 19
jbe@30 20 The modified ``ipairs(seq)`` and the new ``string.concat(sep, seq)`` functions
jbe@30 21 accept either a table or a function as ``seq``. This is demonstrated in the
jbe@30 22 following examples:
jbe@0 23
jbe@0 24 require "seqlua"
jbe@0 25
jbe@0 26 t = {"a", "b", "c"}
jbe@0 27
jbe@0 28 for i, v in ipairs(t) do
jbe@0 29 print(i, v)
jbe@0 30 end
jbe@0 31 -- prints:
jbe@0 32 -- 1 a
jbe@0 33 -- 2 b
jbe@0 34 -- 3 c
jbe@0 35
jbe@25 36 print(string.concat(",", t))
jbe@25 37 -- prints: a,b,c
jbe@25 38
jbe@19 39 function alphabet()
jbe@0 40 local letter = nil
jbe@0 41 return function()
jbe@0 42 if letter == nil then
jbe@19 43 letter = "a"
jbe@19 44 elseif letter == "z" 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@23 53 for i, v in ipairs(alphabet()) do
jbe@0 54 print(i, v)
jbe@0 55 end
jbe@0 56 -- prints:
jbe@0 57 -- 1 a
jbe@0 58 -- 2 b
jbe@0 59 -- 3 c
jbe@0 60 -- ...
jbe@0 61 -- 25 y
jbe@0 62 -- 26 z
jbe@0 63
jbe@25 64 print(string.concat(",", alphabet()))
jbe@25 65 -- prints: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
jbe@25 66
jbe@26 67 function filter(f)
jbe@26 68 return function(seq)
jbe@26 69 return coroutine.wrap(function()
jbe@26 70 for i, v in ipairs(seq) do f(v) end
jbe@26 71 end)
jbe@26 72 end
jbe@0 73 end
jbe@19 74
jbe@29 75 alpha_beta_x = filter(function(v)
jbe@28 76 if v == "a" then
jbe@28 77 coroutine.yield("alpha")
jbe@28 78 elseif v == "b" then
jbe@28 79 coroutine.yield("beta")
jbe@28 80 elseif type(v) == "number" then
jbe@23 81 for i = 1, v do
jbe@28 82 coroutine.yield("X")
jbe@23 83 end
jbe@0 84 end
jbe@26 85 end)
jbe@0 86
jbe@29 87 print((","):concat(alpha_beta_x{"a", 3, "b", "c", "d"}))
jbe@28 88 -- prints: alpha,X,X,X,beta
jbe@25 89
jbe@29 90 print((","):concat(alpha_beta_x(alphabet())))
jbe@28 91 -- prints: alpha,beta
jbe@27 92
jbe@0 93
jbe@0 94 C part of the library
jbe@0 95 ---------------------
jbe@0 96
jbe@0 97 In ``seqlualib.h``, the following macro is defined:
jbe@0 98
jbe@0 99 #define seqlua_iterloop(L, iter, idx) \
jbe@0 100 for ( \
jbe@0 101 seqlua_iterinit((L), (iter), (idx)); \
jbe@0 102 seqlua_iternext(iter); \
jbe@25 103 )
jbe@25 104
jbe@25 105 and
jbe@25 106
jbe@25 107 #define seqlua_iterloopauto(L, iter, idx) \
jbe@25 108 for ( \
jbe@25 109 seqlua_iterinit((L), (iter), (idx)); \
jbe@25 110 seqlua_iternext(iter); \
jbe@0 111 lua_pop((L), 1) \
jbe@0 112 )
jbe@0 113
jbe@23 114 This macro allows iteration over either tables or iterator functions as the
jbe@23 115 following example function demonstrates:
jbe@0 116
jbe@0 117 int printcsv(lua_State *L) {
jbe@0 118 seqlua_Iterator iter;
jbe@0 119 seqlua_iterloop(L, &iter, 1) {
jbe@0 120 if (seqlua_itercount(&iter) > 1) fputs(",", stdout);
jbe@0 121 fputs(luaL_tolstring(L, -1, NULL), stdout);
jbe@25 122 // two values need to be popped (the value pushed by
jbe@25 123 // seqlua_iternext and the value pushed by luaL_tolstring)
jbe@25 124 lua_pop(L, 2);
jbe@0 125 }
jbe@0 126 fputs("\n", stdout);
jbe@0 127 return 0;
jbe@0 128 }
jbe@0 129
jbe@11 130 printcsv{"a", "b", "c"}
jbe@11 131 -- prints: a,b,c
jbe@11 132
jbe@11 133 printcsv(assert(io.open("testfile")):lines())
jbe@11 134 -- prints: line1,line2,... of "testfile"
jbe@0 135
jbe@0 136

Impressum / About Us