[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
**Subject**: **Re: Long chains of objects (aka tables)**
**From**: Jay Carlson <nop@...>
**Date**: Sat, 17 May 2014 14:18:12 -0400

On May 17, 2014, at 1:34 PM, Petite Abeille <petite.abeille@gmail.com> wrote:
> On May 17, 2014, at 7:07 PM, Thiago L. <fakedme@gmail.com> wrote:
>
>> I want something like |local v = t?t1?t2?t3|... (actually I want |local v = t?.t1?.t2?.t3|…)
>
> Why don’t you simply write a little function that does exactly that then?
>
> v = get( t, ‘1.2.3.4.5.6.7.8.9’ )
Don't forget to memoize the lambda! ;-)
Inside the definition of get(t, path):
local accessor = my_functions[path]
if accessor then return accessor(t) end
-- imagine the chain is parsed etc
function_body = "return function (t) return t and t.$1 and t.$1.$2 [...] end"
-- idiomatic
accessor = assert(loadstring(function_body))()
my_functions[path] = accessor
return accessor(t)
The chunk could be written
-- only want the first element of varargs
local t=(...)
return t and t.$1 and t.$1.$2
and cut out one level of indirection.
If you want some path elements to be required and some to be optional, you can generate the function body that way too.
You can tune for likely vs unlikely nil; if the chain bombs out early, it's faster to use "t and t.t1 and t.t1.t2" than "v=t and v.t1; v=v and v.t2".
FWIW I slowly remembered you can macro-expand a?b in expressions to
(function(t)
t=t and t.b
return t
end)(a)
which is better than it sounds because it does not capture anything.