[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: nil isn't as unique in Lua 4.1
- From: RLake@...
- Date: Fri, 11 Jan 2002 11:10:50 -0500
John McKenna escribió:
(Quoting Peter Shook)
> >I look at lexically scoped and eventtable and I think "WOW, that's
> >great. That will fix a whole bunch of nasty things in my code." I look
> >at false and I thing "What for?". I guess false just isn't that useful
> >for me. I just hope you don't go and add 0, "0" and "" to the list of
> >false values.
I agree with Peter here
> The problem that false is there to solve is that nil is currently trying
> to be two very different things - "false" and "doesn't exist".
Yes. The question is whether it is the right solution, since it is often
not
necessary to solve it.
> Let's say you have a very lengthy computation that returns either "true"
> or "false". Since it takes such a long time to compute, you decide to
> cache the results in a table. Look up the parameter in the table - if
> you get nil, then either you've already done the calculation and the
> answer was "false", or you haven't done the calculation yet.
function memoise(fn)
local false = {}
local memotag = newtag()
local getter = function(t, k)
local rv = rawget(t, k)
return rv ~= %false and rv
end
local indexer = function(t, k)
local val = %fn(k)
t[k] = val or %false
return val
end
local caller = function(t, k)
return t[k]
end
settagmethod(memotag, "gettable", getter)
settagmethod(memotag, "index", indexer)
settagmethod(memotag, "function", caller)
return settag({}, memotag)
end
If you know the memoised function really only returns true or false, there
is a
slightly simpler solution, but I find the above quite useful. It's possible
to
avoid the call to rawget in getter with a second level of indirection.
There is
also a solution for functions which might accept nil as an argument.
Memoising functions of more than one argument is a lot trickier, but that
wasn't
your question.
> Or maybe you're implementing an object system with inheritance. If a
> field isn't in the child's member table, then look it up in the parent.
> How do you store "false"?
The above model works for this, too. I've really got to get around to
posting
my standard tag method library.
> Or there's Markus Huber's example: you want default values for function
> parameters. If the function gets nil for that parameter, then it can't
> tell if the parameter was missing, or if the caller is trying to pass
> "false".
Define the global false={} and test for its existence. If that doesn't
appeal
to you, use the following:
function with_optional_second_argument(a, ...)
local b = default
if arg.n ~= 0 then b = arg[1] end
-- do whatever you wanted to do
end
> Introducing a real false value means that nil can be "doesn't exist",
> and nothing else. It eliminates a lot of ambiguity.
But it also creates an often unnecessary differentiation. I'd rather work
around the ambiguity when I recognise it.
Rici