Three dubious ways to handle deep indexing

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Three dubious ways to handle deep indexing

Dirk Laurie-2
I want `a.b.c.d.e`. I'm going to test for nil, and I don't care
at what level the missing index is.

1.   x = a and a.b and a.b.c and a.b.c.d and a.b.c.d.e
2.   x = has(a,"b.c.d.e") with
function has(a,idx)
  local j,k = idx:match"([^.]+)%.(.*)"
  if not k then return a[idx]
  else return has(a[j],k)
  end
end
3, debug.setmetatable(nil,{__index=function() return nil end})
x = a.b.c.d.e

Reply | Threaded
Open this post in threaded view
|

Re: Three dubious ways to handle deep indexing

Scott Morgan
On 02/23/2017 12:06 PM, Dirk Laurie wrote:

> I want `a.b.c.d.e`. I'm going to test for nil, and I don't care
> at what level the missing index is.
>
> 1.   x = a and a.b and a.b.c and a.b.c.d and a.b.c.d.e
> 2.   x = has(a,"b.c.d.e") with
> function has(a,idx)
>   local j,k = idx:match"([^.]+)%.(.*)"
>   if not k then return a[idx]
>   else return has(a[j],k)
>   end
> end
> 3, debug.setmetatable(nil,{__index=function() return nil end})
> x = a.b.c.d.e

4: (Shown this before)
-- 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

Scott


Reply | Threaded
Open this post in threaded view
|

Re: Three dubious ways to handle deep indexing

Martin
In reply to this post by Dirk Laurie-2
On 02/23/2017 04:06 AM, Dirk Laurie wrote:

> I want `a.b.c.d.e`. I'm going to test for nil, and I don't care
> at what level the missing index is.
>
> 1.   x = a and a.b and a.b.c and a.b.c.d and a.b.c.d.e
> 2.   x = has(a,"b.c.d.e") with
> function has(a,idx)
>   local j,k = idx:match"([^.]+)%.(.*)"
>   if not k then return a[idx]
>   else return has(a[j],k)
>   end
> end
> 3, debug.setmetatable(nil,{__index=function() return nil end})
> x = a.b.c.d.e

This was my first issue in Lua that annoyed me. Traditional solution
(1.) with infinite "and a.b and a.b.c" hurts my feelings and fingers.

Finally I came to something like solution (2.) (but w/o recursion and
with names list in vararg "...").

Solution (3.) looks neat. Will try it.

-- Martin

Reply | Threaded
Open this post in threaded view
|

Re: Three dubious ways to handle deep indexing

Roberto Ierusalimschy
In reply to this post by Dirk Laurie-2
> I want `a.b.c.d.e`. I'm going to test for nil, and I don't care
> at what level the missing index is.
>
> [...]

PiL 4 suggests the following method:

  E = {}      -- (somewhere in your code)

  ((((a or E).b or E).c or E).d or E).e

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Three dubious ways to handle deep indexing

Soni "They/Them" L.


On 23/02/17 10:35 AM, Roberto Ierusalimschy wrote:

>> I want `a.b.c.d.e`. I'm going to test for nil, and I don't care
>> at what level the missing index is.
>>
>> [...]
> PiL 4 suggests the following method:
>
>    E = {}      -- (somewhere in your code)
>
>    ((((a or E).b or E).c or E).d or E).e
>
> -- Roberto
>

This eats `false`, instead of choking on it.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.