Parcourir la source

'__pairs' can also return a to-be-closed object

Roberto I il y a 2 mois
Parent
commit
4cf498210e
3 fichiers modifiés avec 15 ajouts et 9 suppressions
  1. 7 6
      lbaselib.c
  2. 2 2
      manual/manual.of
  3. 6 1
      testes/nextvar.lua

+ 7 - 6
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_pushvalue(L, 1);  /* state, */
-    lua_pushnil(L);  /* and initial value */
+    lua_pushcfunction(L, luaB_next);  /* will return generator and */
+    lua_pushvalue(L, 1);  /* state */
+    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;
 }
 }
 
 
 
 

+ 2 - 2
manual/manual.of

@@ -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

+ 6 - 1
testes/nextvar.lua

@@ -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