3

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 2

3

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
Sign up to request clarification or add additional context in comments.

2 Comments

This is very interesting and YES it solves my problem to have a generic log function. Another addition I made by assigning flags for each log Classes. Log(Error,... ) Log(Info,... ) Log(Debug, ...) By having additional parameter, I could control verbosity. +1 for your help
This loop for _ in value:gmatch("%%[^%%]") do will match string "5%% less" despite of your intention to skip sequential percent.
2

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

1 Comment

Specifying format will not be a generic solution, My example code is pretty basic but idea was to have completely generic Logger

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.