Thread Tools Display Modes
11-10-11, 11:18 PM   #1
SaraFdS
A Fallenroot Satyr
 
SaraFdS's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 24
_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
__________________
Sará the Insane
  Reply With Quote
11-11-11, 01:18 AM   #2
ballagarba
A Fallenroot Satyr
 
ballagarba's Avatar
Join Date: Mar 2009
Posts: 22
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...

Last edited by ballagarba : 11-11-11 at 01:26 AM.
  Reply With Quote
11-11-11, 01:18 AM   #3
suicidalkatt
A Rage Talon Dragon Guard
 
suicidalkatt's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 331
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.

Last edited by suicidalkatt : 11-11-11 at 01:24 AM.
  Reply With Quote
11-11-11, 01:22 AM   #4
ballagarba
A Fallenroot Satyr
 
ballagarba's Avatar
Join Date: Mar 2009
Posts: 22
Offtopic, what's the tag for showing lua-code like that? With syntax highlighting and all.
  Reply With Quote
11-11-11, 01:23 AM   #5
suicidalkatt
A Rage Talon Dragon Guard
 
suicidalkatt's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 331
Originally Posted by ballagarba View Post
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 ']'.

Last edited by suicidalkatt : 11-11-11 at 01:25 AM.
  Reply With Quote
11-11-11, 01:24 AM   #6
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,323
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.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
11-11-11, 05:09 AM   #7
SaraFdS
A Fallenroot Satyr
 
SaraFdS's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 24
Originally Posted by ballagarba View Post
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
Originally Posted by suicidalkatt View Post
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.
Originally Posted by SDPhantom View Post
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?
__________________
Sará the Insane
  Reply With Quote
11-11-11, 05:34 AM   #8
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,323
Originally Posted by SaraFdS View Post
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.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
11-11-11, 09:00 AM   #9
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
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.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
11-11-11, 09:41 AM   #10
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
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.
  Reply With Quote
11-11-11, 10:53 AM   #11
SaraFdS
A Fallenroot Satyr
 
SaraFdS's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 24
Originally Posted by SDPhantom View Post
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)
Originally Posted by Torhal View Post
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.
__________________
Sará the Insane
  Reply With Quote
11-11-11, 03:05 PM   #12
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,323
Originally Posted by SaraFdS View Post
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);
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » _G for local variables


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off