lua-users home
lua-l archive

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



On 25-Jul-04, at 12:33 PM, Mark Hamburg wrote:

I thought about making import just use the __index metamethod but was left feeling fuzzy on what to do in the event of an error. If it really acts just like a table, then it should just return nil if the value isn't present.

Yes, that is a good argument. Of course, later attempts to use the
result as a table would generate a run-time error, but it would be
nicer to be more precise. I was actually assuming that it was ok
to throw an exception from a table lookup; an alternative would be
to return nil and ask careful programmers to type:

local Observations = assert(import.Observations)

which would also allow the programmer to try something else, or probe for optional plugins. (True for the function version, as well, of course.)

If you are expecting bundle names to be hierarchical, then the function is probably better, but they could certain both exist simultaneously.

the complexity in mine may be from the fact that I take explicit steps to detect and disallow cyclic import.

There was quite a discussion about cyclic import at some point. How does one handle mutually dependent packages? It is not always easy to eliminate this. Indeed, to my mind this is the semantic difference between "require" and "import": require defines a dependency (this package won't work without the other one) while import defines a need:(I'm about to use this package, I need it now.) Of course, that is just me, and the particular words are not important, but there do seem to be two use cases.

I've been thinking of extending my import function to allow specifying a series of names to extract from the exported value:

Perhaps this little function is actually useful:

function ensure(tab, ...)
  for i = 1, args.n do
    if tab[args[i]] then args[i] = tab[args[i]]
                    else error("Table is missing key '"
                               .. tostring(args[i])
                               .."'")
    end
  end
  return unpack(args)
end

local addObserver, removeObserver, notifyObservers =
        ensure(import "com.baymoon.Observations",
               "add", "remove", "notify" )


But, actually, I would personally go for lazy name loading instead; i.e. the import function makes a table and attaches loader routines to each name, without actually running the loader routines.

I do feel strongly that such loader routines should exist, for reasons I have ranted about sufficiently before. :)

R.