lua-users home
lua-l archive

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


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