[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: assert with formatting
- From: Sean Conner <sean@...>
- Date: Fri, 13 Jul 2018 16:17:43 -0400
It was thus said that the Great Hisham once stated:
> On 13 July 2018 at 11:23, Pierre Chapuis <catwell@archlinux.us> wrote:
> >> Um, but wouldn't
> >>
> >> format_assert(a == 1 , "'a' should be '%d', but was '%s'",1,tostring(a))
> >>
> >> *also* compose the message even if a equals 1? Lua doesn't do lazy
> >> evaluation.
> >
> > It would call `tostring(a)` in all cases, but it would not call `string.format` because that branch of the `if` would never be evaluated.
> >
> > I am not entirely sure if there is a real performance gain, though.
>
> Not only the cost of running string.format, but also memory:
>
> for i = 1, N do
> local a = do_something(i)
> assert(a == 1, ("`a` should be `%d`, but was `%s`"):format(1,a))
> end
>
> This produces N strings in memory to be garbage collected (adding time
> to GC runs), while this doesn't:
>
> for i = 1, n do
> local a = do_something(i)
> format_assert(a == 1, "`a` should be `%d`, but was `%s`", 1, a)
> end
>
> (Note the removed tostring(), or else we'd still get N strings; so if
> necessary the implementation of format_assert should do that instead.)
And then a isn't a string or a number and you get another error while
trying to log an error; calling tostring() is safer.
But if you are really concerned about GC and performance, you'll need to
force lazy evaluation on this:
format_assert(a == 1 , function()
return ("'a' should be %d, but was '%s'"):format(1,tostring(a)))
end)
This is assuming that format_assert() can check if the second parameter is a
function and call it. Doing it this way, the string isn't constructed until
it's needed (that's what lazy evaluation is).
-spc