How do I create a function that returns the first carrier, non-empty string passed to it?

I am trying to implement a function that returns the first non-empty string from variables passed to it. Unfortunately some of these variables can be zero, so the naive approach

function first_non_empty(...)
    for i, item in ipairs({...}) do
        if item ~= nil and item ~= '' then
            return item
        end
    end
    return ''
end

      

doesn't work: ipairs leaves as soon as it encounters a null value. This can be eliminated by changing the requirements so that the variables cannot be nile, or by passing the length of the function, so the length of the table should not rely on ipairs

or by wrapping all parameters in the function so that none of them is explicitly equal

function first_non_empty_func(...)
    for i, func in ipairs({...}) do
        local item = func()
        if item ~= nil and item ~= '' then
            return item
        end
    end
    return ''
end

function fn(p)
    local f = function() return p end
    return f
end

-- change callers to first_non_empty_func(fn(a), fn(b), fn(c))

      

However, both of these solutions complicate the function prototype. Is there a function that takes an ordered list of parameters, some of which may be nil, that returns the first of those parameters, which is a non-nil rather than an empty string?

+3


source to share


3 answers


select('#', ...)

can be used to get the number of arguments supplied, so here's an alternative that doesn't use table.pack

:



function first_non_empty_pack(...)
    for i = 1, select('#', ...) do
        local item = select(i, ...)
        if item ~= nil and item ~= '' then
            return item
        end
    end
    return ''
end

      

+3


source


Use table.pack

which keeps all records nil and returns the number of records in the field n

:



function first_non_empty_pack(...)
    local t = table.pack(...)
    for i = 1, t.n do
        local item = t[i]
        if item ~= nil and item ~= '' then
            return item
        end
    end
    return ''
end

      

+4


source


A simpler approach is to use recursion. No additional tables created, etc .:

function first_non_empty(item, ...)
    if item ~= nil and item ~= '' then return item end
    return first_non_empty(...)
end

      

But the list must end with some ending marker. For example, boolean 'false', indicating no non-nil, non-blank lines.

+1


source







All Articles