lua-users home
lua-l archive

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


>> -- somewhere, e.g. module
>> local nothing = setmetatable({}, {
>>       __index = function(nothing)
>>               return nothing
>>       end,
>>       __call = function()
>>               return nil
>>       end,
>> })
>>
>> function maybe(tab)
>>       return setmetatable({}, {
>>               __index = function(_, key)
>>                       if tab[key] then
>>                               return maybe(tab[key])
>>                       else
>>                               return nothing
>>                       end
>>               end,
>>               __call = function()
>>                       return tab
>>               end,
>>       })
>> end
>>
>> -- then
>>
>> a = { b = { c = 123 } }
>>
>> print( maybe(a).b.c() )  -- 123
>> print( maybe(a).x.c() )  -- nil
>>
>> --
>>
>> I'm not 100% happy with it, but I think it'd cover most my use cases.

On Thu, Jul 9, 2015 at 9:16 AM, Roberto Ierusalimschy
<roberto@inf.puc-rio.br> wrote:
>
> When all fields are present, that code will create two new tables plus
> two new closures at each dot: for instance, maybe(a).b.c() creates four
> new objects. That sounds quite expensive.

But it does not have to be that expensive.

do

  local protect     =  false
  local nothing_mt  =  {}
  local nothing     =  setmetatable ( {}, nothing_mt )
  local follow

  function nothing_mt.__index ( t, k )
    if follow then  follow  =  follow [ k ]  end
    return nothing  end

  function nothing_mt.__call ()
    local t  =  follow
    follow   =  nil
    protect  =  false
    return t  end

  function maybe ( t )
    assert ( not protect )
    protect  =  true
    follow   =  t
    return nothing  end

end

a = { b = { c = 123 } }

print ( maybe (a).b.c() )
print ( maybe (a).x.c() )

In the above, the assert will fail if maybe is called again before
__call.  But that could probably be fixed as well, such that only one
new closure would be needed for each nested maybe call.  And those
closures could be cached and reused.

-Parke