Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua, the problem about the order of setting __gc

Tags:

lua

Can anybody tell me why code1 and code2 have different results but code3 and code4 have the same.
code1:

o = {x = "hi"}
mt = {}
mt.__gc = function (o) print(o.x) end
setmetatable(o, mt)
o = nil
collectgarbage()

The result of code1:

hi

code2:

o = {x = "hi"}
mt = {}
setmetatable(o, mt)
mt.__gc = function (o) print(o.x) end
o = nil
collectgarbage()

The result of code2:nothing
The only difference between code1 and code2 is that the statement setmetatable(o, mt) and the statement mt.__gc = function (o) print(o.x) end are executed in different order. Their results are totally different: the first one printed hi while the other printed nothing. Does the order of setting meta-table to a object finally affect the result? if it does, why code3 and code4 have the same result?
code3

o = {x = "hi"}
mt = {}
setmetatable(o, mt)
mt.__index = function () print("no such key") end
print(o["x"])
print(o["y"])

code4

o = {x = "hi"}
mt = {}
mt.__index = function () print("no such key") end
setmetatable(o, mt)
print(o["x"])
print(o["y"])

Both the result of code3 and code4 are the same:

hi
no such key
nil

like image 908
Phoenix Chao Avatar asked Oct 05 '20 03:10

Phoenix Chao


Video Answer


1 Answers

Since Lua 5.2, Lua tables support metamethod __gc. Quoth the second paragraph:

For an object (table or userdata) to be finalized when collected, you must mark it for finalization. You mark an object for finalization when you set its metatable and the metatable has a field indexed by the string "__gc". Note that if you set a metatable without a __gc field and later create that field in the metatable, the object will not be marked for finalization.

This is exactly your case: the second sentence describes the first example, the third, the second.

like image 177
Alexander Mashin Avatar answered Oct 18 '22 20:10

Alexander Mashin