Lua, Modify print function

Viewed 1257

I am writing a generic Log() function in lua which utilizes lua print function:

Log (variable, 'String: %s ', str, 'Word: %d', w)

Currently I'm using below approach:

print(string.format (variable, 'String: %s ', str, 'Word: %d', w))

I tried something like:

Log = function(...) begin
return print(string.format(...))
end

But it doesn't work, Is this correct approach? Or Is there any better more generic way to get this done?

2 Answers

If you just want to print a sequence of values, you can do that with print:

print(variable, 'String: %s ', str, 'Word: %d', w)

What you seem to want is something more complicated. Your algorithm seems to be:

  1. For each argument:
    1. If the argument is not a string, then convert it to a string and print it.
    2. If the argument is a string, figure out how many % patterns it has (let us call this number k). Pass string.format the current argument string and the following k parameters, printing the resulting string. Advance k parameters.

That's a much more complicated algorithm than can be done in a one-line system.

Using Lua 5.3, here's what such a function would look like (note: barely tested code):

function Log(...)
    local values = {}

    local params = table.pack(...)

    local curr_ix = 1
    while (curr_ix <= params.n) do
        local value = params[curr_ix]
        if(type(value) == "string") then
            --Count the number of `%` characters, *except* for
            --sequential `%%`.
            local num_formats = 0
            for _ in value:gmatch("%%[^%%]") do
                num_formats = num_formats + 1
            end

            value = string.format(table.unpack(params, curr_ix, num_formats + curr_ix))

            curr_ix = curr_ix + num_formats
        end

        values[#values + 1] = value
        curr_ix = curr_ix + 1
    end

    print(table.unpack(values))
end

I don't think your current approach works, because the first argument of string.format expects the format specifier, not the rest of the arguments.

Anyway, this is the way to combine formatting and printing together:

Log = function(...)
  return print(string.format(...))
end

And call it like this:

Log("String: %s  Number: %d", 'hello' , 42)

Also, it might be better to make the format specifier argument more explicit, and use io.write instead of print to get more control over printing:

function Log(fmt, ...)
  return io.write(string.format(fmt, ...))
end
Related