Well, the hooking is much less of an issue since 2.0. Destructive hooking (or any hooking really) of the lower-level functions often leads to tainting the default UI, and breaking things (damn that disappearing pet bar!) I was merely pointing out that sometimes handy side-effect of avoiding later hooks to the function.
Sylv's not asking for an explaination, he wants to know EXACTLY what the lua interpreter does. See his post above with the LOADK and CALL stuff.
The real question I've got is, no matter how the "true" lua handles this... how does WoW's? Is it's _G tha same as "pure" lua's, or did they just set a global named _G = getfenv(0) somewhere? That could potentially change things if we were to discover that "local _G = _G" is pointless (or slower) in pure lua if WoW's version is a "real" global...
Okey, it's not bytecode, but poking at WoW... getfenv(0), _G and _G._G are all the same table (literally, exact same address for each)
I don't think anyone was saying _G.SomeValue was better, were they? If you know the full name you should be using it directly, by all means. You only need _G (or getglobal) when the name is in some way variable... like _G[frame:GetName().."Icon"] or _G["SomeActionBar"..i]
You need to learn scope :P Locals in functions is good, take it out to the file level where you need access to things across functions. Locals declared at file-level scope can only be seen by anything else at that scope, so you need to do it for each file (and expose ones somewhere you need across files... attaching to your global object/table is the usual way.
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.
If, however, you call said function an asston, like say OnUpdate, by all means make it a local.
Good god, I hate this "quote reply quote reply quote reply quote reply quote reply quote reply quote reply" shit... I just skipped the last 8 or so replies... ugh...
Quote from Bam »
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.
Well avoiding globals is a quality issue for the most part, it is a performance concern as well. 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. Either way, the whole point is pushing as much as you can out of the global scope, to keep it clean of (extra) clutter, and to speed up things. Even a slight speed bost is worth it unless it's some complex convoluted method to get that boost. This ain't complex at all, it's just creating a local reference and replacing a function call with a table lookup.
The better method, of course, is to try to avoid looking up things by name as much as possible.
AddOnMainFrame:SetScript("OnClick", function() MyAddOn:MainFrame_OnClick(this) end )
I think I'm going to stab you.
-- If you need 'self' for MyAddOn:
AddOnMainFrame:SetScript("OnClick", function(f) self:MainFrame_OnClick(f) end )
-- If you don't... don't define MainFrame_OnClick with a colon... or better yet define it as a local function
AddOnMainFrame:SetScript("OnClick", MyAddOn.MainFrame_OnClick )
AddOnMainFrame:SetScript("OnClick", MyLocalMainFrame_OnClick )
-- Or if you only use the function in this one place...
-- Do shit here...
-- In terms of functionality, this code
-- is identical to this code
MyFrameName = CreateFrame('Frame')
Wrong. The "name" is not just the global scope variable name, but it's also passed back from frame:GetName()... which Blizzy loves to use.
The whole point here is, as with the quasi-OO design, to avoid polluting the global namespace. every Blizzard frame and function out there is in the global namespace, but you don't have to be. Your addon object should, ideally, be the only global you declare. If a frame needs some external access, you can just add it into that table.
Besides that, learning to use locals is the first big step in improving your addon's performance. Blizzy's super heavy use of getglobal() makes me a sad panda.
It's not really that Blizzy wants to keep their frames from being destroyed... it's that the process of destroying a frame, and potentially all it's children, and figuring out what to do with frames anchored to the frame... well isn't exactly a simple process. Frames aren't something that need to be dynamically destroyed and remade, as the UI layout is fairly static after creation.