lua-users home
lua-l archive

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


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.