Ah, yes, I forgot the assumption of not containing cycles. I meant to write that, actually...
Quote: The idea of modules is that every variable inside them is relative to the module environment (_M), you don't need to explicitly state it.
By using _M in front of functions that are meant for the public, it is quickly clear to me what is what. A function that is declared local up at the top won't be obviously local when redeclared further down. So, my convention is that a function meant for the public is _M and a function meant for just the module will be local, and later declared without a _M.
It's wordy for small files like a table copying, but it makes things really easy when you are designing large classes for OOP type stuff, where you have more than just a few functions lying around.
Quote: You need the "seeall" or it doesn't find things like "type".
Indeed; I didn't paste all that stuff because it's just a heap of locals at the beginning that I thought were unnecessary obfuscation for pasting the code.
I don't like using seeall for a small self-contained module because I don't necessarily want to inherit the global environment for indexing. That is a very big deal when defining objects. If you are writing an object module, and you use seeall, then if you try to get a field of the object that doesn't exist (i.e. is nil) it'll go into _G to get it. If you are then also using the 'strict' module, you will get an error if it doesn't exist. And if it *does* exist, you are not getting what you think you are getting.
The main reason I don't use '...' but actually name the module is because it's meant to be a library-type thing that sits around and is called by lots of people; its name is essentially static so I figure I might as well just name it. I don't feel terribly strongly about this, though, unlike the 'seeall' problems I describe above.
Quote: This version makes the helper function copyTable a local declaration (and thus a private function).
I suppose you could do that. I left it public so that people could call it directly if they wanted to. I think it was for historic reasons: at first, I didn't have the helper interfaces so all my calls were to copyTable; had I made it public it would have required going through and changing an awful lot of code, which I didn't feel like doing.
Quote: This version renames the functions as "deep" and "shallow" for easier use.
I don't do that because what I pasted is actually just a subset of a whole utility file with various other routines; it wouldn't make sense for me to have just 'deep' and 'shallow' in there.
Quote: Then I start to worry that we are testing for "deep" and "shallow" for every subtable, which is really a decision that needs to be made once only.
Yes, I thought about doing that, but I figured it didn't matter a whole lot (for now) since string checks are essentially free in Lua. And my tables were fairly "shallow" in depth, so it wasn't a big issue. But it is something I was thinking of getting around to doing, but now you've done it for me. :) |