lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

It was thus said that the Great Hisham once stated:
> On 13 July 2018 at 11:23, Pierre Chapuis <> 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)))

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).