'__pairs' can also return a to-be-closed object
This commit is contained in:
13
lbaselib.c
13
lbaselib.c
@@ -279,21 +279,22 @@ static int luaB_next (lua_State *L) {
|
|||||||
|
|
||||||
static int pairscont (lua_State *L, int status, lua_KContext k) {
|
static int pairscont (lua_State *L, int status, lua_KContext k) {
|
||||||
(void)L; (void)status; (void)k; /* unused */
|
(void)L; (void)status; (void)k; /* unused */
|
||||||
return 3;
|
return 4; /* __pairs did all the work, just return its results */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int luaB_pairs (lua_State *L) {
|
static int luaB_pairs (lua_State *L) {
|
||||||
luaL_checkany(L, 1);
|
luaL_checkany(L, 1);
|
||||||
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
||||||
lua_pushcfunction(L, luaB_next); /* will return generator, */
|
lua_pushcfunction(L, luaB_next); /* will return generator and */
|
||||||
lua_pushvalue(L, 1); /* state, */
|
lua_pushvalue(L, 1); /* state */
|
||||||
lua_pushnil(L); /* and initial value */
|
lua_pushnil(L); /* initial value */
|
||||||
|
lua_pushnil(L); /* to-be-closed object */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
||||||
lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */
|
lua_callk(L, 1, 4, 0, pairscont); /* get 4 values from metamethod */
|
||||||
}
|
}
|
||||||
return 3;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6799,11 +6799,11 @@ In particular, you may set existing fields to nil.
|
|||||||
@LibEntry{pairs (t)|
|
@LibEntry{pairs (t)|
|
||||||
|
|
||||||
If @id{t} has a metamethod @idx{__pairs},
|
If @id{t} has a metamethod @idx{__pairs},
|
||||||
calls it with @id{t} as argument and returns the first three
|
calls it with @id{t} as argument and returns the first four
|
||||||
results from the call.
|
results from the call.
|
||||||
|
|
||||||
Otherwise,
|
Otherwise,
|
||||||
returns three values: the @Lid{next} function, the table @id{t}, and @nil,
|
returns the @Lid{next} function, the table @id{t}, plus two @nil values,
|
||||||
so that the construction
|
so that the construction
|
||||||
@verbatim{
|
@verbatim{
|
||||||
for k,v in pairs(t) do @rep{body} end
|
for k,v in pairs(t) do @rep{body} end
|
||||||
|
|||||||
@@ -905,13 +905,18 @@ local function foo1 (e,i)
|
|||||||
if i <= e.n then return i,a[i] end
|
if i <= e.n then return i,a[i] end
|
||||||
end
|
end
|
||||||
|
|
||||||
setmetatable(a, {__pairs = function (x) return foo, x, 0 end})
|
local closed = false
|
||||||
|
setmetatable(a, {__pairs = function (x)
|
||||||
|
local tbc = setmetatable({}, {__close = function () closed = true end})
|
||||||
|
return foo, x, 0, tbc
|
||||||
|
end})
|
||||||
|
|
||||||
local i = 0
|
local i = 0
|
||||||
for k,v in pairs(a) do
|
for k,v in pairs(a) do
|
||||||
i = i + 1
|
i = i + 1
|
||||||
assert(k == i and v == k+1)
|
assert(k == i and v == k+1)
|
||||||
end
|
end
|
||||||
|
assert(closed) -- 'tbc' has been closed
|
||||||
|
|
||||||
a.n = 5
|
a.n = 5
|
||||||
a[3] = 30
|
a[3] = 30
|
||||||
|
|||||||
Reference in New Issue
Block a user