lua-users home
lua-l archive

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


On Tue, Jan 11, 2011 at 10:30 AM, Dirk Laurie <dpl@sun.ac.za> wrote:
> 2. nil is not a first-class value and may therefore not be either
>    a key or a value.

And here's another 'special' property of nil: it is considered to mark
the end of an iterator. So simple single-valued sequences may not
contain nil.

It would be convenient to have an animal called 'nada', which behaves
like nil, except in a table context (Mark Hamburg has made such a
suggestion, but was shot down for trying to introduce a null/undefined
distinction from JavaScript).

You can _almost_ implement nada in Lua

local MT = { }

function MT:__index(k)
  error('cannot index nil',2)
end;

MT.__newindex = MT.__index

function MT:__call()
  error('cannot call nil',2)
end

function MT:__tostring()
  return 'nil'
end

function MT.__eq(a,b)
  local ta = type(a)
  return ta=='nil' or ta=='table'
end

nada = {}
setmetatable(nada,MT)
debug.setmetatable(nil,MT)

So the naive idea was that nil == nada because they share a metatable,
but that's not how __eq works. According to the manual __eq logic does
this:

       if type(op1) ~= type(op2) then return nil end
       local mm1 = metatable(op1)['__eq']
       local mm2 = metatable(op2)['__eq']]
       if mm1 == mm2 then return mm1 else return nil end

The type() check knocks us out directly, but notice that the logic is
not 'have the same metatable', it is 'may have different metatables
that share the same __eq'. This subtle difference makes __eq play nice
with inheritance.

Yes, a __type metamethod would be nice (especially if it can work on
this level) but I imagine it would make type() more expensive.

So, without __eq, one still has to check whether a value is nil or
nada, but in other respects it behaves the same and is a useful
non-hole value to put into arrays of objects.

steve d.