Sitelet https://github.com/lua-stdlib/lua-stdlib/commit/2aa5c0119ea2aa9906c21d00411983db094229b6
Skip to content

Commit 2aa5c01

Browse files
committed
refactor: consolidate and speed-up ielems and elems functions.
* specs/table_spec.yaml (elems, ielems): Move from here... * specs/lua_spec.yaml (elems, ielems): ...to here. * specs/functional_spec.yaml (fold): Adjust ielems import. * lib/std/base.lua (ielems): Remove. * lib/std/table.lua (elems, ielems): Remove. * lib/std/lua.lua (elems, ielems): Wrap ipairs and pairs, taking care to honor __ipairs and __pairs metamethods, for a noticeable speedup. * lib/std/debug.lua, lib/std/list.lua, lib/std/tree.lua: Adjust ielems imports and examples. * build-aux/sanity-cfg.mk (sc_error_message_uppercase): Add specs/lua_spec.yaml. * NEWS: Update. Signed-off-by: Gary V. Vaughan <gary@gnu.org>
1 parent 6e598e8 commit 2aa5c01

14 files changed

Lines changed: 134 additions & 123 deletions

File tree

‎NEWS‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ Stdlib NEWS - User visible changes
2626
`#` and matching `~`, plus new mathematical operators `%` and `^`, and
2727
relational operators, `<`, `<=`, `>` and `>=`.
2828

29-
- New `table.elems` and `table.ielems` functions for iterating table
30-
values cleanly, and for orthogonality between std.table, std.base,
31-
std.list and std.set.
32-
3329
- New `functional.nop` function, for use where a function is required
3430
but no work should be done.
3531

@@ -38,6 +34,9 @@ Stdlib NEWS - User visible changes
3834
`std.lua.eval`, and `std.lua.memoize` (original access points exported
3935
by earlier releases will be preserved for the forseeable future).
4036

37+
- New `lua.ielems` and `lua.elems` functions for iterating sequences cleanly,
38+
while respecting `__ipairs` and `__pairs` metamethods respectively.
39+
4140
- `lua.memoize` now propagates multiple return values correctly.
4241
This allows memoizing of functions that use the `return nil, "message"`
4342
pattern for error message reporting.

‎build-aux/sanity-cfg.mk‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
exclude_file_name_regexp--sc_error_message_uppercase = ^lib/std/(list|optparse).lua|specs/(base|debug)_spec.yaml$$
1+
exclude_file_name_regexp--sc_error_message_uppercase = ^lib/std/(list|optparse).lua|specs/(base|debug|lua)_spec.yaml$$
22

33
EXTRA_DIST += build-aux/sanity-cfg.mk

‎lib/std/base.lua‎

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -532,23 +532,6 @@ local function export (M, decl, fn, ...)
532532
end
533533

534534

535-
--- An iterator over the integer keyed elements of a table.
536-
-- @tparam table t a table
537-
-- @treturn function iterator function
538-
-- @treturn *t*
539-
-- @return `true`
540-
local function ielems (t)
541-
local n = 0
542-
return function (t)
543-
n = n + 1
544-
if n <= #t then
545-
return t[n]
546-
end
547-
end,
548-
t, true
549-
end
550-
551-
552535
--- Iterator returning leaf nodes from nested tables.
553536
-- @tparam function it table iterator function
554537
-- @tparam tree|table tr tree or tree-like table
@@ -594,7 +577,6 @@ local M = {
594577
deprecate = deprecate,
595578
export = export,
596579
getmetamethod = getmetamethod,
597-
ielems = ielems,
598580
leaves = leaves,
599581
nop = nop,
600582
prototype = prototype,

‎lib/std/debug.lua‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ local _DEBUG = require "std.debug_init"._DEBUG
3333

3434
local base = require "std.base"
3535
local functional = require "std.functional"
36+
local lua = require "std.lua"
3637
local string = require "std.string"
3738

3839
local export = base.export
40+
local ielems = lua.ielems
41+
3942
local M = { "std.debug" }
4043

4144

@@ -51,7 +54,7 @@ local M = { "std.debug" }
5154
-- @usage s = tabify {...}
5255
local tabify = functional.compose (
5356
-- map (elementfn, iterfn, unnbound_table_arg)
54-
functional.bind (functional.map, {string.tostring, base.ielems}),
57+
functional.bind (functional.map, {string.tostring, ielems}),
5558
-- table.concat (unbound_strbuf_table, "\t")
5659
functional.bind (table.concat, {[2] = "\t"}))
5760

‎lib/std/functional.lua‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ end)
131131
-- @treturn table elements e for which `p (e)` is not falsey.
132132
-- @see collect
133133
-- @usage
134-
-- > filter ("|e| e%2==0", std.list.elems, List {1, 2, 3, 4})
134+
-- > filter (lua.lambda "|e| e%2==0", lua.elems, {1, 2, 3, 4})
135135
-- {2, 4}
136136
export (M, "filter (func, func, any*)", function (p, i, ...)
137137
local t = {}
@@ -153,7 +153,7 @@ end)
153153
-- @return result
154154
-- @see std.list.foldl
155155
-- @see std.list.foldr
156-
-- @usage fold (math.pow, 1, std.list.elems, List {2, 3, 4})
156+
-- @usage fold (math.pow, 1, lua.elems, {2, 3, 4})
157157
export (M, "fold (func, any, func, any*)", function (f, d, i, ...)
158158
local r = d
159159
for e in i (...) do
@@ -180,7 +180,7 @@ end
180180
-- @treturn table results
181181
-- @see filter
182182
-- @usage
183-
-- > map (function (e) return e % 2 end, std.list.elems, List {1, 2, 3, 4})
183+
-- > map (function (e) return e % 2 end, lua.elems, {1, 2, 3, 4})
184184
-- {1, 0, 1, 0}
185185
export (M, "map (func, func, any*)", function (f, i, ...)
186186
local t = {}

‎lib/std/list.lua‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ local _ARGCHECK = require "std.debug_init"._ARGCHECK
3232

3333
local base = require "std.base"
3434
local func = require "std.functional"
35+
local lua = require "std.lua"
3536
local object = require "std.object"
3637

3738

38-
local argcheck, argerror, argscheck, ielems, prototype =
39-
base.argcheck, base.argerror, base.argscheck, base.ielems, base.prototype
39+
local argcheck, argerror, argscheck, prototype =
40+
base.argcheck, base.argerror, base.argscheck, base.prototype
41+
local ielems = lua.ielems
4042

4143
local Object = object {}
4244

‎lib/std/lua.lua‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,30 @@ local export, getmetamethod = base.export, base.getmetamethod
1212
local M = { "std.lua" }
1313

1414

15+
16+
--[[ ================= ]]--
17+
--[[ Helper Functions. ]]--
18+
--[[ ================= ]]--
19+
20+
21+
local function wrapiterator (factory, ...)
22+
-- Capture wrapped ctrl variable into an upvalue...
23+
local fn, istate, ctrl = factory (...)
24+
-- Wrap the returned iterator fn to maintain wrapped ctrl.
25+
return function (state, _)
26+
local v
27+
ctrl, v = fn (state, ctrl)
28+
if ctrl then return v end
29+
end, istate, true -- wrapped initial state, and wrapper ctrl
30+
end
31+
32+
33+
34+
--[[ ================= ]]--
35+
--[[ Module Functions. ]]--
36+
--[[ ================= ]]--
37+
38+
1539
--- A rudimentary case statement.
1640
-- Match `with` against keys in `branches` table, and return the result
1741
-- of running the function in the table value for the matching key, or
@@ -42,6 +66,32 @@ export (M, "eval (string)", function (s)
4266
end)
4367

4468

69+
--- An iterator over all elements of a sequence.
70+
-- @function elems
71+
-- @tparam sequence x a sequence
72+
-- @treturn function iterator function
73+
-- @treturn sequence *x*, the sequence being iterated over
74+
-- @treturn int *key*, the previous iteration key
75+
-- @usage
76+
-- for v in elems {a = 1, b = 2, c = 5} do process (v) end
77+
export (M, "elems (string|table)", function (x)
78+
return wrapiterator (getmetamethod (x, "__pairs") or pairs, x)
79+
end)
80+
81+
82+
--- An iterator over the integer keyed elements of a sequence.
83+
-- @function ielems
84+
-- @tparam sequence x a sequence
85+
-- @treturn function iterator function
86+
-- @treturn sequence *x*, the sequence being iterated over
87+
-- @treturn int *index*, the previous iteration index
88+
-- @usage
89+
-- for v in ielems {"a", "b", "c"} do process (v) end
90+
export (M, "ielems (List|list|string)", function (x)
91+
return wrapiterator (getmetamethod (x, "__ipairs") or ipairs, x)
92+
end)
93+
94+
4595
--- Memoize a function, by wrapping it in a functable.
4696
--
4797
-- To ensure that memoize always returns the same results for the same

‎lib/std/set.lua‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
]]
1313

1414
local base = require "std.base"
15+
local lua = require "std.lua"
1516
local container = require "std.container"
1617

1718
local Container = container {}
19+
local ielems = lua.ielems
1820
local prototype = base.prototype
1921

2022

@@ -206,7 +208,7 @@ Set = Container {
206208
_type = "Set",
207209

208210
_init = function (self, t)
209-
for e in base.ielems (t) do
211+
for e in ielems (t) do
210212
insert (self, e)
211213
end
212214
return self

‎lib/std/string.lua‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ end)
158158
-- @return list of `{from, to; capt = {captures}}`
159159
-- @see std.string.tfind
160160
-- @usage
161-
-- for t in list.elems (finds ("the target string", "%S+")) do
161+
-- for t in lua.elems (finds ("the target string", "%S+")) do
162162
-- print (tostring (t.capt))
163163
-- end
164164
export (M, "finds (string, string, int?, boolean|:plain?)", function (s, p, i, ...)

‎lib/std/table.lua‎

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313

1414
local base = require "std.base"
15+
local lua = require "std.lua"
1516

16-
local export, getmetamethod, ielems =
17-
base.export, base.getmetamethod, base.ielems
17+
local export, getmetamethod = base.export, base.getmetamethod
1818

1919

2020
local M = { "std.table" }
@@ -64,7 +64,7 @@ local function merge_namedfields (t, u, keys, nometa)
6464
if not nometa then
6565
setmetatable (t, getmetatable (u))
6666
end
67-
for k in ielems (keys) do
67+
for _, k in ipairs (keys) do
6868
t[k] = u[k]
6969
end
7070
return t
@@ -128,25 +128,6 @@ export (M, "clone_select (table, [table], boolean|:nometa?)",
128128
function (...) return merge_namedfields ({}, ...) end)
129129

130130

131-
--- An iterator over all values of a table.
132-
-- @function elems
133-
-- @tparam table t a table
134-
-- @treturn function iterator function
135-
-- @treturn table *t*
136-
-- @treturn boolean `true`
137-
-- @usage for func in elems (_G) do ... end
138-
export (M, "elems (table)", function (t)
139-
local k, v = nil
140-
return function (t)
141-
k, v = next (t, k)
142-
if k then
143-
return v
144-
end
145-
end,
146-
t, true
147-
end)
148-
149-
150131
--- Return whether table is empty.
151132
-- @function empty
152133
-- @tparam table t any table
@@ -157,16 +138,6 @@ export (M, "empty (table)", function (t)
157138
end)
158139

159140

160-
--- An iterator over the integer keyed elements of a table.
161-
-- @function ielems
162-
-- @tparam table t a table
163-
-- @treturn function iterator function
164-
-- @treturn table *t*
165-
-- @treturn boolean `true`
166-
-- @usage for value in ielems {"a", "b", "c"} do ... end
167-
export (M, "ielems (table)", ielems)
168-
169-
170141
--- Invert a table.
171142
-- @function invert
172143
-- @tparam table t a table with `{k=v, ...}`

0 commit comments

Comments
 (0)