As I explained a few post above, I like to "import" global variables like that. But not for performance reasons (it will be minor anyway). I do it to have a clean interface between my code and the code "outside". This way you can see exactly what the code depends on by just looking at the initial imports.
It's true that you have to be a bit careful about functions that are likely to be hooked. For those I use an explicit lookup in _G. Again to make it clear that I am accessing code from another place.
I do all of these tricks because I essentially don't like languages with dynamic binding. They are dangerously error-prone. As many errors as possible should be caught at "compile-time" instead of at run-time. When the language does not help me in this respect, I resort to using a strict discipline when coding.
Bam, problem with your boilerplate is that there is a finite limit to the number of locals. I'd only declare ones I need. Also the upvalues take a bit of memory (same size as a new empty table) for every function that needs an upval... so again it's a tradeoff, size for speed. Hence why I say if you're not calling _G a frequent number of times (or any of those things in your boilerplate) it's probably better to just eat the tiny bit of perf needed to make the global lookup.
I doubt the total number of locals will become a problem ever. I'll deal with that if it happens. :)
For me the primary tradeoff is "code quality versus performance (size and speed)". The number of closures created in a file is generally low and static. I guess you are right that if I dynamically create a lot of closures, then I am paying a price. However, I assume that Lua knows to only capture the locals actually used in those closures. So I don't think that's a major problem either.
The reason I have this boilerplate is not only convenience. It's also to enforce a simple rule: I don't allow any globals after the initial "import". I can check that using a script. That would be harder to do if some globals were allowed and some weren't.
Well avoiding globals is a quality issue for the most part, it is a performance concern as well.
Since this solves both issues at the same time, I'm not going to argue against it. :)
Quote from tekkub »
Sure, the advantage is slight, but cutting out the function call (getglobal) and the global lookup (local _G = _G) are a good thing to do if you are using getglobal on the scale Blizzy does. However, if you only make a small handful of calls, I'd just use _G directly without making a local copy.
I simply start every Lua file with a boiler-plate "import" of commonly used globals including the _G. Then that issue is solved and I don't have to worry more about it. :)
My boiler-plate preamble to each file looks like this:
he didn't list 'self'. So why he's passing it I don't know.
Though I don't know the rest of the code, I'm sure the idea is that the functions in Actions will be replaced later on by something more interesting. So the above is just an initialization with a dummy function.
But I would strongly suggest that you do such an initialization differently:
self.Actions = DoNothing
where DoNothing is a local variable defined elsewhere like this
local function DoNothing()end
You can call it something else if you like. The main point of this code is to clearly show the intention that we are deliberately using an empty function. Well-chosen names is the best kind of code documentation - and often the only necessary form of documentation.
In the past, I've been quite liberal with getglobal(). In a different thread, I learned that getglobal() is nothing but a wrapper function that does _G[ <blah blah> ].
That's correct. However, the main reason you should avoid global variables (wether they hold frames or something else) is neither pollution nor performance. It's a matter of code quality. Reading and writing global variables introduces a side-effect of your code. It means that you cannot look at a small piece of code (a function for example) in isolation and say for sure what it does since it depends on the values of the non-local variables at the time the code is executed.
There is much more to say about code quality in general, of course. And there are usually trade-offs that need to be made. But as a rule of thumb you should prefer local variables with as small a scope as possible. A global variable has the largest possible scope. That's why it's bad. :)
-- In terms of functionality, this code
-- is identical to this code
MyFrameName = CreateFrame('Frame')
Well, that depends what functionality you mean. In the second case above, the frame does not actually have a name. That is, MyFrameName:GetName() will return nil. That would mean you cannot use it with some API functions or other parts of Blizzard's code.
I understand that I can create the frame like the code above, but, once the function is over, I don't think I can refer to that particular frame again without a name.
Of course you can. Just assign the reference to a variable or field that is accessible from the other places in your code where you need it. That's basic Lua programming. In this respect a frame reference is no different from any other value (strings, tables, numbers, etc.) that you create in one place and use in another.
Quote from Ringleron »
I guess "child objects" could be nameless more as hiding the parent object would also hide the children.
Not really sure what you mean. Named frames don't offer any additional functionality by themselves. But as I mentioned above, there are a few API functions that require a name rather than a frame reference. But that's merely a sad limitation of those functions.
Quote from Ringleron »
Also, if names have no impact on memory, then does that mean that a nameless frame will take (theoretically) the same memory space as a named frame.
Well, the name itself and the global variable associated with it will take up a small amount of memory. But that's so small, it's not worth mentioning really.
Quote from Ringleron »
I really wish there are ways to "destroy" manually created frames (frames created by the CreateFrame function).
Indeed. But frames can't be destroyed ever. No matter how you created them. That's simply a feature Blizzard has not implemented. There are probably some difficulties doing that. But they are not Lua related.
Quote from Ringleron »
Anyways, something to think about when coding. I guess the rule of thumb is if the frame won't be referred to again after the initial creation, then it could be nameless.
Umm, re-read the "rules" I posted above for when you stricly need names. There may be a few other situations that I have missed though.
There actually is one situation where I sometimes do use named frames even though it's not stricly needed. That's when I want to debug visible frame layout. A tool like Iriel's DevTools will show the name of a frame when you hover over it. This can be quite useful sometimes.