Home > Software design >  Is there a way I can reduce this in-a-row kind of repeating Lua conditions?
Is there a way I can reduce this in-a-row kind of repeating Lua conditions?

Time:12-13

I think I already could know the answer... but just to be totally sure, sometimes I find myself writing conditionals like:

if type(value) ~= "function" and type(value) ~= "table" and type(value) ~= "thread" and type(value) ~= "userdata" then
    --do whatever...
end

And every time I wonder if there couldn't be a more economical way to do it, for example, like:

if type(value) ~= "function" and ~= "table" and ~= "thread" and ~= "userdata" then
    --do whatever...
end

I mean, not having to repeat the whole individual condition all the times since the first part (type(value)) is always going to the same. Of course the above wouldn't work, but could it be any other way I'm simply not seeing? I hope it makes sense...

CodePudding user response:

I do it like this. Coming from R, I am used to having the %in% function. Below, I create a function that works in a similar way in lua:

-- return true if one of the elements of tab is equal to el
local function in_tab(el, tab)

  for _, v in pairs(tab) do
    if el == v then return true end
  end
  return false
end

And you can call it like this:

if not in_tab(type(object), 
              { "table", "userdata", "thread", "function" }) then ...

end

Given how fast pairs() is, this does not seem to incur any penalty on the computation time. In addition, it comes in very handy all the time.

Of course, if you keep testing against the same values, a much simpler solution is a simple lookup:

local dts = { table = true, userdata = true, thread = true }

if dts[ type(object) ] then ... end

Of course, in case of function you would have to do this:

dts["function"] = true

because neither { function = true } nor dts.function = true are allowed.

CodePudding user response:

Why not create a function that mimics isinstance from Python?

local function isinstance(obj, ...)
    local obj_type = type(obj)
    for _, v in pairs{...} do
        if v == obj_type:
            return true
    return false
end

Usage:

if not isinstance(value, "function", "table", "thread", "userdata") then
    -- do whatever...
end

You may even want to add additional functionality like matching the "type" based on the metatable or disambiguating integers and floats.

  • Related