what is the nicest way to check from Lua if a structure has a field?
I want the following loop.
for j, gref in ipairs(posting.job.general_refs) do
if gref.unit_id == some_unit_id then
do_stuff
end
end
but I don't know what gref is going to be. If it's general_ref_unit_slaughtereest or general_ref_unit_workerst, it has unit_id, but general_ref_building_holderst doesn't.
In current form, the loop throws
Cannot read field general_ref_building_holderst.unit_id: not found.
stack traceback:
[C]: in metamethod '__index'
The usual solution is to use pcall() around a function that just accesses the field, then handle any errors as you see fit. For example:
local ok, val = pcall(function()
return gref.unit_id
end)
Feel free to use better variable names, of course. Docs for pcall() can be found here:
https://www.lua.org/manual/5.3/manual.html#pdf-pcallThis might not be very performant. If you run into bottlenecks, I don't believe there is a way to look up what fields a given type has from Lua (although the C++ layer that __index calls definitely has this information), but you could build a table of "type => fields" or "type => has_unit_id_field" mappings yourself, or cache it as you go.
Ideally, it would just return nil in this case, but this may be too much to ask
I think it would be too big of a compatibility break at this point. I think the behavior is mostly for parity with other languages where accessing an invalid field throws an error. Granted, in C++, that error occurs at compile-time, but in Ruby it would occur at runtime like in Lua. There's also the matter of existing fields that can be defined but nil (i.e. null pointers in C++), which the current behavior makes more clear to Lua.