lua-users home
lua-l archive

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




On Thursday, May 1, 2014, Thiago L. <fakedme@gmail.com> wrote:

On 01/05/2014 22:56, Sean Conner wrote:
It was thus said that the Great Andrew Starks once stated:
Here is a hack that I like a lot:

```lua

debug.setmetatable(nil, {
     __index = function(t, i)
         return nil
     end
})

local this = {}

if this.field.does.NOT.exist == nil then
     print('no error!')
end

--> no error!
```
   Wow.

   I'm of two minds on this.  On the one hand, I love the idea, because there
are times when I want this behavior.  On the other hand, this can hide some
serious bugs in a code base.  On the gripping hand [1], I wouldn't know how
to deal with a codebase that does this.

   -spc (I never thought that nil could have a metatable associated with it)

[1]     The two hardest things in computer science: naming, cache
        invalidation and off-by-one errors.

There's no need for a hack:

NIL_VALUE = {}
softmt = { __index = function(t,k) if rawget(t,k) == nil then return NIL_VALUE else return rawget(t,k) end end }
setmetatable(NIL_VALUE,softmt)

softtable = {}
setmetatable(softtable,softmt)

val = softtable.some.invalid.key
if val == NIL_VALUE then return "it works!" end

Best part? If you don't have a __metatable protected metatable:

oldmt = getmetatable(t)
setmetatable(t,softmt)
val = t.insert.some.long.chain.here
if val == NIL_VALUE then val = nil end
setmetatable(t,oldmt)
-- etc

While it's not as nice as Groovy[1] it does the job just fine...

[1] http://groovy.codehaus.org/Null+Object+Pattern


The thing is, this hack works with every table in existence, not just ones that don't have an __index method that is available for override. 

The trouble(?) is, it works with nothing, too:

local foo = nil
 
print(foo.bar)
--> nil

It kind of breaks my brain. I'm not near a real computer, so I'll have to try out what happens when a table with __index assigned to a table returns nil... Does the rawget kill the fun? It might not... Probably need more sleep to hypothesize. :)

-Andrew