[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: __call?
- From: RLake@...
- Date: Fri, 19 Dec 2003 16:33:03 -0500
As Edgar pointed out a couple of days ago (and a couple of years ago),
there is no obvious reason why table.foreach should check to see if its
argument is a function. If it is not callable, a perfectly understandable
error message would be generated when table.foreach tries to call it.
The situation is a little different for some other places where functions
are used polymorphically, such as in the __index/__newindex metamethods
(and some other metamethods), the "legacy" for-in construct, string.gsub()
and probably some others I have forgotten about.
A slightly similar issue occurs with "table-like" userdata (i.e. userdata
with __index and maybe __newindex metamethods). These should "act like"
tables, and they usually do, but not always: for example, the environment
must be a "real" table, and again there is the issue with
__index/__newindex metamethods. (Also, the metatable must be a "real"
table.)
It is not sufficient to say that a table-like object has an __index
metamethod and a function-like object has a __call metamethod, because
objects can have both (tables with __call metamethods, for example). So
attempting to use the tableness or functionness of an object to select the
appropriate behaviour is doomed to ambiguity if both tableness and
functionness are possibilities. (This is not the case with, for example,
string.gsub, although it would be perfectly reasonable for string.gsub to
use the first capture as a table key if the replace argument were
table(like).)
So there is a certain lack of orthogonality. But that is not a disaster.
I would suggest that, to the extent possible, library functions not check
for function/table-ness, and rather leave it to lua_{get, set, call,
pcall} to generate the error message -- it may not be as precise about
identifying which argument is in error, but it is otherwise an adequate
error message. (And avoiding the use of lua_raw{get, set} would probably
be a good idea.) Some solution like Alex's is possible for places where
either a table or a function is acceptable with different behaviours, and
possibly also for the case of environment tables. Allowing userdata as
metatables is arguably not worth the overhead it would generate, although
there are applications for it.
I know that some of us have thought (out loud, either on this list or in
private correspondence) about whether it would be possible to simply merge
the concept of functions and the concept of tables. Unfortunately, there
are a number of subtle semantic issues and charming though the idea is, it
is probably not worthwhile either.
Rici