I agree that limiting this functionality to "?." and "?[" is probably
better.
A more general "?" operator might be _possible_, but doesn't actually
seem terribly _useful_.
I was mulling this over last night, and I think I've entirely changed my mind. I'm now fairly certain that a more general postfix operator is the better way to go. What I hadn't seen earlier is how elegantly it could come together.
Here's what I'm currently planning:
'?' is the "Safe Navigator Operator" -- a piece of syntax sugar that converts:
expr? to (expr or _SAFE)
_SAFE, meanwhile, is the second upvalue placed inside any new chunk. It's initial value is a unique userdata with a metatable that defines __call, __pairs, __ipairs, __index, and __newindex as nullops.
And that's it.
object.glow?()
will cause object to glow if it has a glow function defined.
object.clock?.current_time = time()
sets the current time of object's clock, if it has a clock.
returns the first 3 characters of object's name, if object has a name.
for k,v in pairs(object.table?) do
iterates though the members of object's table, if it has one
The semantics are such that you can easily change the default behavior from a nullop to printing a non-breaking warning -- just define:
local _SAFE = setmetatable({},{_index=function(...) print_warning(..) end})
The general version would be slightly slower than the patch I originally posted, and it would impose some slight memory costs. But my hunch is that in virtually all situations, those additional costs would be negligible. Of course, I have yet to code anything up, so, there may be some big drawback or complication that I'm missing. But at the moment, it's looking like a hugely promising Saturday afternoon project :)
-Sven