WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   _G for local variables (https://www.wowinterface.com/forums/showthread.php?t=41779)

SaraFdS 11-10-11 11:18 PM

_G for local variables
 
After searching and trying almost an hour to find a way to access local variables with dynamic names (and facepalming when the most simple solution sprang to my mind...), I'm still wondering: is there a way, analogue to _G for global variables, to access local variables?

lua Code:
  1. -- the _G way
  2. globalvar1 = "foo"
  3. globalvar2 = "bar"
  4. for i=1, 2 do
  5.   _G["globalvar"..i] -- do sth with it
  6. end
  7.  
  8. -- trying it local
  9. local localvar1 = "foo"
  10. local localvar2 = "bar"
  11. for i=1, 2 do
  12.   ?? -- how could those be accessed?
  13. end
  14.  
  15. -- my workaround
  16. local localvar = {
  17.   "foo",
  18.   "bar"
  19. }
  20. for i=1, 2 do
  21.   localvar[i] -- do sth with it
  22. end

ballagarba 11-11-11 01:18 AM

Hmm, correct me if I'm wrong but couldn't you just imitate the _G with a local version, since as far as I understand, _G is just a table.

So:

lua Code:
  1. local _L = {}
  2.  
  3. _L['localvar1'] = 'foo'
  4. _L['localvar2'] = 'bar'
  5.  
  6. for i=1, 2 do
  7.     _L["localvar"..i] -- do sth with it
  8. end

Not as neat assignment though...

suicidalkatt 11-11-11 01:18 AM

I think what you're trying to say, is there a different way of getting the global variable without using this?
Lua Code:
  1. _G["varname"]

In the usage you're describing, no.

ballagarba 11-11-11 01:22 AM

Offtopic, what's the tag for showing lua-code like that? With syntax highlighting and all.

suicidalkatt 11-11-11 01:23 AM

Quote:

Originally Posted by ballagarba (Post 247102)
Offtopic, what's the tag for showing lua-code like that? With syntax highlighting and all.


It's the same as 'code', but instead of 'code' it's 'lua'.


^ WRONG

use '[' highlight=lua ']' closed with '[' /highlight ']'.

SDPhantom 11-11-11 01:24 AM

As for a true Lua global, there's no way to define or read dynamic locals. However as you've demonstrated, you may define a single local table that holds additional data as key/value pairs. I would advise against this unless absolutely necessary as table entries consume more resources than locals themselves. I follow the simple rule, tables are only for list/structure data, everything else is to stay in locals.

SaraFdS 11-11-11 05:09 AM

Quote:

Originally Posted by ballagarba (Post 247100)
Hmm, correct me if I'm wrong but couldn't you just imitate the _G with a local version, since as far as I understand, _G is just a table.

Effectively that's what I've done in my workaround (just different variable names), seems you got that idea faster than I did :D
Quote:

Originally Posted by suicidalkatt (Post 247101)
I think what you're trying to say, is there a different way of getting the global variable without using this?
Lua Code:
  1. _G["varname"]

In the usage you're describing, no.

No, I was looking for a way to get a local variable, similar to how you use _G to get a global variable.
Quote:

Originally Posted by SDPhantom (Post 247104)
As for a true Lua global, there's no way to define or read dynamic locals. However as you've demonstrated, you may define a single local table that holds additional data as key/value pairs. I would advise against this unless absolutely necessary as table entries consume more resources than locals themselves. I follow the simple rule, tables are only for list/structure data, everything else is to stay in locals.

So, it'd be faster and more efficient to hardcode everything that needs to be done for each local, instead of putting them into a table and iterating over it?

SDPhantom 11-11-11 05:34 AM

Quote:

Originally Posted by SaraFdS (Post 247111)
So, it'd be faster and more efficient to hardcode everything that needs to be done for each local, instead of putting them into a table and iterating over it?

If the data is unrelated to each other, yes. I don't know the code that you're trying to use this method for, so I can't state any more specific ways to make your code efficient. As for any rule of thumb, there can be and often are exceptions.

Torhal 11-11-11 09:00 AM

If you need such a construct for local variables, you're probably structuring your code incorrectly; scoping is a logical tool, not something to be avoided.

Vlad 11-11-11 09:41 AM

local addonName, _L = ...

Could then use _L table for local addon storage, accessible across files, but shouldn't be used for standard data access like OnUpdate loop constantly accessing the table _L.data={} at certain index would take more resources than having a local data = ... where the data is directly stored in the variable local to that file. Table within table is slower than just one table.

Anyway, probably not useful info.

SaraFdS 11-11-11 10:53 AM

Quote:

Originally Posted by SDPhantom (Post 247112)
If the data is unrelated to each other, yes. I don't know the code that you're trying to use this method for, so I can't state any more specific ways to make your code efficient. As for any rule of thumb, there can be and often are exceptions.

I'm creating two FontStrings to display timers. The event that updates them fires ~every second. To not overwrite them if nothing changed, I'm caching their state, also in two local vars.
lua Code:
  1. local BGtext = {
  2.     MiniMapBattlefieldFrame:CreateFontString(nil,nil,"GameFontNormal"),
  3.     MiniMapBattlefieldFrame:CreateFontString(nil,nil,"GameFontNormal")
  4. }
  5. local laststatus = {"",""}
  6. BGtext[1]:SetPoint("RIGHT",MiniMapBattlefieldFrame,"LEFT")
  7. BGtext[2]:SetPoint("TOPRIGHT",BGtext[1],"BOTTOMRIGHT")
  8. MiniMapBattlefieldFrame:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")
  9. MiniMapBattlefieldFrame:SetScript("OnEvent",function(s,e,a)
  10.     if e == "UPDATE_BATTLEFIELD_STATUS" then
  11.         for i=1,2 do
  12.             local status, map = GetBattlefieldStatus(i)
  13.             if status == "queued" then
  14.                 BGtext[i]:SetText(MySecondsToTime((GetBattlefieldEstimatedWaitTime(i)-GetBattlefieldTimeWaited(i))/1000))
  15.             else
  16.                 if status ~= laststatus[i] then
  17.                     laststatus[i] = status
  18.                     if status == "confirm" then
  19.                         BGtext[i]:SetText(map)
  20.                     else
  21.                         BGtext[i]:SetText("")
  22.                     end
  23.                 end
  24.             end
  25.         end
  26.     end
  27. end)
Quote:

Originally Posted by Torhal (Post 247118)
If you need such a construct for local variables, you're probably structuring your code incorrectly; scoping is a logical tool, not something to be avoided.

The scope ain't a problem, it's just the fact, that I cannot access the variables the way I need/want to. I could have avoided this problem by simply declaring all 4 vars as globals, but that would have been the wrong way as far as I know.

SDPhantom 11-11-11 03:05 PM

Quote:

Originally Posted by SaraFdS (Post 247133)
I'm creating two FontStrings to display timers. The event that updates them fires ~every second. To not overwrite them if nothing changed, I'm caching their state, also in two local vars.
lua Code:
  1. local BGtext = {
  2.     MiniMapBattlefieldFrame:CreateFontString(nil,nil,"GameFontNormal"),
  3.     MiniMapBattlefieldFrame:CreateFontString(nil,nil,"GameFontNormal")
  4. }
  5. local laststatus = {"",""}
  6. BGtext[1]:SetPoint("RIGHT",MiniMapBattlefieldFrame,"LEFT")
  7. BGtext[2]:SetPoint("TOPRIGHT",BGtext[1],"BOTTOMRIGHT")
  8. MiniMapBattlefieldFrame:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")
  9. MiniMapBattlefieldFrame:SetScript("OnEvent",function(s,e,a)
  10.     if e == "UPDATE_BATTLEFIELD_STATUS" then
  11.         for i=1,2 do
  12.             local status, map = GetBattlefieldStatus(i)
  13.             if status == "queued" then
  14.                 BGtext[i]:SetText(MySecondsToTime((GetBattlefieldEstimatedWaitTime(i)-GetBattlefieldTimeWaited(i))/1000))
  15.             else
  16.                 if status ~= laststatus[i] then
  17.                     laststatus[i] = status
  18.                     if status == "confirm" then
  19.                         BGtext[i]:SetText(map)
  20.                     else
  21.                         BGtext[i]:SetText("")
  22.                     end
  23.                 end
  24.             end
  25.         end
  26.     end
  27. end)

I would suggest not queueing the status. I don't know the exact CPU impact between caching/contitional checking and just doing a flat out call to change the text, but my instinct would be to just let the code run through. You can also clean things up by running an iterator through your FontString object table.

lua Code:
  1. local BGtext = {
  2.     MiniMapBattlefieldFrame:CreateFontString(nil,nil,"GameFontNormal");
  3.     MiniMapBattlefieldFrame:CreateFontString(nil,nil,"GameFontNormal");
  4. };
  5.  
  6. BGtext[1]:SetPoint("RIGHT",MiniMapBattlefieldFrame,"LEFT");
  7. BGtext[2]:SetPoint("TOPRIGHT",BGtext[1],"BOTTOMRIGHT");
  8.  
  9. MiniMapBattlefieldFrame:RegisterEvent("UPDATE_BATTLEFIELD_STATUS");
  10. MiniMapBattlefieldFrame:SetScript("OnEvent",function(s,e,a)
  11.     if e=="UPDATE_BATTLEFIELD_STATUS" then
  12.         for i,j in ipairs(BGtext) do
  13.             local status,map=GetBattlefieldStatus(i);
  14.             if status=="queued" then
  15.                 j:SetText(MySecondsToTime((GetBattlefieldEstimatedWaitTime(i)-GetBattlefieldTimeWaited(i))/1000));
  16.             elseif status == "confirm" then
  17.                 j:SetText(map);
  18.             else
  19.                 j:SetText("");
  20.             end
  21.         end
  22.     end
  23. end);


All times are GMT -6. The time now is 10:52 AM.

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