WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   More than 200 local variables (https://www.wowinterface.com/forums/showthread.php?t=57812)

Walkerbo 02-09-20 05:41 PM

More than 200 local variables
 
Hi all

My addon stops working once I have more than 200 local variables, the error gives me the following message.
Code:

4x AAA\AAA 8.4.8.3.lua:5589: main function has more than 200 local variables
I understand that I can reduce the number of variables to keep under that 200 cap but I would like to know why such a cap exists?


Also I can define variables using
Code:

local a, b, c, d, e = 1, 2, 3, 4, 5
However this still counts as 5 local variables, is there a way to define local variables in a way that dose not increase the overall count of local variables?

Kanegasi 02-09-20 08:30 PM

Define a local table at the top of your addon and use keys instead of separate variables.

For example:

Lua Code:
  1. -- instead of this
  2. local a, b, c, d, e = 1, 2, 3, 4, 5
  3.  
  4. -- use this
  5. local vars = {}
  6. vars.a, vars.b, vars.c, vars.d, vars.e = 1, 2, 3, 4, 5

You can even use the provided addon table in the second vararg return that's handed to each of your addon's files.

Lua Code:
  1. local addonName, addonTable = ... -- the very first line of your addon file

This addon table is shared across all your Lua files under a single .toc file.

I honestly wasn't aware of a local variable cap, but I've had tables with thousands of entries in them.

Seerah 02-09-20 08:49 PM

It's a limit in Lua itself, and has to do with how much room it has for local variables in one scope, iirc.

Walkerbo 02-09-20 09:27 PM

Hi Kanegasi & Seerah

Thanks for the feedback and advice, both really appreciated.

SDPhantom 02-11-20 10:34 AM

Quote:

Originally Posted by Kanegasi (Post 335102)
Define a local table at the top of your addon and use keys instead of separate variables.

For example:

Lua Code:
  1. -- instead of this
  2. local a, b, c, d, e = 1, 2, 3, 4, 5
  3.  
  4. -- use this
  5. local vars = {}
  6. vars.a, vars.b, vars.c, vars.d, vars.e = 1, 2, 3, 4, 5

The entire appeal of using local variables aside from limiting scope is you save an index lookup in the global table. Putting variables in a local table completely negates this since you're re-adding the index operation you were trying to save.

jeruku 02-11-20 11:38 AM

Quote:

Originally Posted by SDPhantom (Post 335113)
The entire appeal of using local variables aside from limiting scope is you save an index lookup in the global table. Putting variables in a local table completely negates this since you're re-adding the index operation you were trying to save.

Yes, but in this case the number of local variables exceeds Lua's capacity for a single scope. I mean, if you're using 200+ local variables a table can be upvalued no differently and though table lookups aren't as fast as a local variable it's not using 200+ local variables.

Seerah 02-11-20 03:41 PM

At least it's a local table and not a global one. ;)

SDPhantom 02-12-20 08:12 AM

There are still better options. Making sure you put local variables only in the scope they're being used (you can force a scope if you need using a do ... end block). Limiting what functions you make local references of. Etc.

Seerah 02-12-20 04:23 PM

I agree. It's possible that the code could be optimized.

Walkerbo 08-26-20 07:52 PM

Hi all

Sorry for the necro thread but I like to keep the same subjects together instead of creating multiple threads.

Some follow up questions.

I have hit the 200 limits again as I have implemented new features and functionality.

Should functions all be local as well or is it better to use complicated/unusual names to ensure there is no cross-pollination? is the same for frame names as well?

Is it better to have functions and frames to be in separate lua files?

Cheers

Zlodo 08-27-20 09:46 AM

It's 200 local variable per function, correct? So if you exceeded it you probably have a gigantic, unwieldy function that can be split into simpler functions. Keep in mind that the top level of a Lua file is also a function.

Walkerbo 08-28-20 07:24 PM

Hi Zlodo

I don't have locals inside functions as each variable exists within its function.

It is each frame, button and function that are local; I have a few workarounds such as having frame and button names in a table, eg;
Lua Code:
  1. local framesNbuttons = {frameA, frameB, buttonA, buttonB}
  2.  
  3. framesNbuttons.frameA = CreateFrame("Frame")
  4.  
  5. framesNbuttons.buttonA = CreateFrame("Button")

I was just wondering if there is a better way to approach this issue.

Further, could I do the same thing with functions?
Lua Code:
  1. local functions = {functionA, functionB}
  2.  
  3. functions.functionsA = function runFunctionA ()

I have tried this with no success, yet I am not sure if this is a correct way of using functions in a table or not.

Kanegasi 08-28-20 07:46 PM

Lua Code:
  1. local functions = {}
  2. functions.functionA = function()
  3.     -- stuff here
  4. end

Seerah 08-28-20 08:00 PM

Quote:

Originally Posted by Walkerbo (Post 336709)
Lua Code:
  1. local framesNbuttons = {frameA, frameB, buttonA, buttonB}
  2.  
  3. framesNbuttons.frameA = CreateFrame("Frame")
  4.  
  5. framesNbuttons.buttonA = CreateFrame("Button")

That doesn't do exactly what you think it does. Your code is creating a table that looks like this:
Lua Code:
  1. local framesNbuttons = {
  2.      [1] = frameA,
  3.      [2] = frameB,
  4.      [3] = buttonA,
  5.      [4] = buttonB,
  6.      ["frameA"] = <yourframe>,
  7.      ["buttonA"] = <yourbutton>,
  8. }
Of course, since frameA, frameB, ... are nil at the time of declaring your table, they aren't actually stored in it and those four numerical keys are tossed at the next garbage collection. So... pointless, really.

Just do:
Lua Code:
  1. local framesNbuttons = {}
  2. framesNbuttons.frameA = CreateFrame("Frame")
  3. framesNbuttons.buttonA = CreateFrame("Button")

Fizzlemizz 08-28-20 08:28 PM

Or create single frames with their component parts as keys on the frame.

Lua Code:
  1. local frameA = CreateFrame("Frame", nil, UIParent)
  2. frameA.Button1 = CreateFrame("Button", nil, frameA)
  3. frameA.Texture1 = frameA:CreateTexture()
  4. frameA.SubFrame1 = CreateFrame("Frame", nil, frameA))
  5. frameA.SubFrame1.Button1 = CreateFrame("Button", nil, frameA.SubFrame1)
1 local used.

MunkDev 08-29-20 08:48 AM

I think your code is severely flawed if you have 200 local variables in a single scope. You should read tutorials on how Lua works, especially I think you'll find tables interesting, and some tutorials on programming in general.

Walkerbo 09-01-20 09:53 PM

Hi all

@MunkDev; I can almost guarantee that my code is flawed and likely very inefficient; I am self-taught with no background in coding at all. :p

@Seerah; thanks for detailing how the table laid out, this was extremely helpful as it really showed how I was using some tables wrong.

@Fizzlemizz; thanks for the example code, this put Seerah's explanation into action and has been a massive help in the way I approach tables and frames.

Just a follow-up question;

Is this chunk;
Lua Code:
  1. local frameA = CreateFrame("Frame", frameA, UIParent)
  2. frameA.Button1 = CreateFrame("Button", frameAButton1, frameA)
  3. frameA.Button1:ClearAllPoints()
  4. frameA.Button1:SetPoint("CENTER", 0, 0)
  5. frameA.Button1:SetSize(40, 40)
the same as;
Lua Code:
  1. local frameA = CreateFrame("Frame", frameA, UIParent)
  2. frameAButton1 = CreateFrame("Button", frameAButton1, frameA)
  3. frameAButton1:ClearAllPoints()
  4. frameAButton1:SetPoint("CENTER", 0, 0)
  5. frameAButton1:SetSize(40, 40)

In the first chunk, I add the button and the button properties directly to the frame.

In the second I add the button to the frame and then add the properties to the button itself.

Both chunks seem to work but I do not know which one is the proper/correct way of coding this.

Fizzlemizz 09-01-20 11:34 PM

Lua Code:
  1. local frameA = CreateFrame("Frame", "frameA", UIParent)
  2. frameAButton1 = CreateFrame("Button", "frameAButton1", frameA)
  3. frameAButton1:ClearAllPoints()
  4. frameAButton1:SetPoint("CENTER", 0, 0)
  5. frameAButton1:SetSize(40, 40)

frameA is a local
frameAButton1 is a global

I added quotes around the frame names as without them, it would just be the same as using nil unless as variables they had been initialised earlier.

As someone once told me, frames are just special types of tables.

Lua Code:
  1. local frameA = CreateFrame("Frame", "frameA", UIParent)
  2. frameA["Button1"] = CreateFrame("Button", "frameAButton1", frameA)
  3. frameA["Button1"]:ClearAllPoints()
  4. frameA["Button1"]:SetPoint("CENTER", 0, 0)
  5. frameA["Button1"]:SetSize(40, 40)
is the same as the original.

Even:
Lua Code:
  1. local f = CreateFrame("Frame", "frameA", UIParent)
  2. f = CreateFrame("Button", "$parentButton1", f)
  3. f:ClearAllPoints()
  4. f:SetPoint("CENTER", 0, 0)
  5. f:SetSize(40, 40)
Would reduce the number of locals used as you are just re-using the one local. Although doing this you lose the local reference to the top level frame but you could still reference it using the frames name ("frameA") as these are added to the global table (note the use of $parent in the button name)

Lua Code:
  1. frameA:SetSize(100, 100)
  2. frameAButton1:SetText("New Button Label")
This is very much the old XML way of doing things before XML frames had the parentKey attribute.

This being the case,
Code:

local frameA = CreateFrame("Frame", "frameA", UIParent)
local frameA would be fine as a local.

"frameA" would be rubbish as a frame name. Being created as a global there's too much chance of a clash (I forget how it woks but I'm pretty sure first frame with a name is added to the global table, any others with the same name are ignored).

Walkerbo 09-02-20 09:49 PM

Hi all

@Fizzlemizz Thanks for your more detailed explanation, the simple statement of "As someone once told me, frames are just special types of tables." makes things crystal clear for me. :)

Thanks to all for your help.

Cheers


All times are GMT -6. The time now is 01:05 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI