Thread Tools Display Modes
05-13-13, 05:37 AM   #1
Jonisaurus
An Aku'mai Servant
 
Jonisaurus's Avatar
Join Date: Aug 2011
Posts: 35
Concatenating a string+number to be an argument

Hello

I'm using Neal's wonderful !Beautycase addon that lets you create borders through a simple function.

Code:
CreateBorder(FrameName, Bordersize, r, g, b, Paddingamount)
Pretty simple.

I am using this function to create borders around my action bar buttons. Each of them are their own frame and I create a border around each of those frames through one function / frame.

I want to simplify this.

Since all of the action buttons are named the same except for the number at the end (MultiBarRightButton1 etc. for example) I want to create a function where I can assign multiple numerical values to "x" and then concatenate them with the framename "MultiBarRightButton" so that the number "x" goes at the end of the string.

The problem is that the CreateBorder function won't work with an argument in quotation marks (duh) and I don't know how I can concatenate it to e.g.
Code:
y = "MultiBarRightButton" .. x
and then have "y" be a valid argument inside parentheses.

If this is really obvious, I'm sorry, I'm a beginner. :P
  Reply With Quote
05-13-13, 05:49 AM   #2
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
If the FrameName parameter doesn't allow strings, it's a very confusing parameter name. Assuming it accepts frames, not frame names, do this:

Code:
for i = 1, 12 do
	CreateBorder(_G["MultiBarRightButton"..i], whateverelseyouwanttoputhere)
end
_G is the table with global variables, and you can get a frame with its name as the key.
  Reply With Quote
05-13-13, 07:44 AM   #3
Jonisaurus
An Aku'mai Servant
 
Jonisaurus's Avatar
Join Date: Aug 2011
Posts: 35
Originally Posted by Haleth View Post
If the FrameName parameter doesn't allow strings, it's a very confusing parameter name. Assuming it accepts frames, not frame names, do this:

Code:
for i = 1, 12 do
	CreateBorder(_G["MultiBarRightButton"..i], whateverelseyouwanttoputhere)
end
_G is the table with global variables, and you can get a frame with its name as the key.
May I kiss you? This worked perfectly.

The CreateBorder function indeed does not accept frame names, only frames.

Sadly I don't quite understand what the reference to the global variable table does to make it work here.

Am I correct to assume it has something to do with the WoW CreateFrame function and the fact that function stores the frame name in a global variable?

Does the _G point to the frame itself when I look up the frame's name with a string?

I'd be very thankful if you could explain what happens here.

Last edited by Jonisaurus : 05-13-13 at 07:48 AM.
  Reply With Quote
05-13-13, 10:09 AM   #4
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Originally Posted by Jonisaurus View Post
Sadly I don't quite understand what the reference to the global variable table does to make it work here.

Am I correct to assume it has something to do with the WoW CreateFrame function and the fact that function stores the frame name in a global variable?

Does the _G point to the frame itself when I look up the frame's name with a string?

I'd be very thankful if you could explain what happens here.
_G holds all named objects inheriting UIObject (created through the widget API), and all other global variables as well.

You can write /dump _G in the chatbox to see all global variables.

Example:
lua Code:
  1. test = {}
  2. -- is the same as:
  3. _G['test'] = {}
  4.  
  5. --
  6. local test = CreateFrame('Frame', 'test')
  7. -- is the same as:
  8. CreateFrame('Frame', 'test')
  9. local test = test
  10. -- but not the same as the following:
  11. -- a reference for the frame is passed to the global environment, but the frame is unnamed.
  12. _G['test'] = CreateFrame('Frame')
More info in the lua manual under 5.1

Last edited by ravagernl : 05-13-13 at 10:22 AM.
  Reply With Quote
05-13-13, 11:41 AM   #5
Jonisaurus
An Aku'mai Servant
 
Jonisaurus's Avatar
Join Date: Aug 2011
Posts: 35
If I understand correctly then the only way to look up a frame that is created with a local variable is if it was given a name through arg2 of the CreateFrame function.

And the CreateFrame arg2 creates a name as a global STRING in _G, but it also creates a global VARIABLE in _G, and both point to the same frame?

But since I couldn't concatenate my STRING to a VARIABLE the workaround was to look up the STRING name of the frame in _G which then also pointed to the frame?

Correct?

Thanks btw!

Last edited by Jonisaurus : 05-13-13 at 11:57 AM.
  Reply With Quote
05-13-13, 12:41 PM   #6
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Originally Posted by Jonisaurus View Post
If I understand correctly then the only way to look up a frame that is created with a local variable is if it was given a name through arg2 of the CreateFrame function.
Not entirely. There are other ways, but in that case the method of getting the frame reference through the global environment is not available.

And the CreateFrame arg2 creates a name as a global STRING in _G, but it also creates a global VARIABLE in _G, and both point to the same frame?
If one removed the reference to the frame in the global table(by nullifying it) and made a local reference beforehand, then my reasoning would be that the frame would still exist in the local environment, but not in the global environment. I have not checked this so I'm not entirely sure, but this almost never happens. So yes.

But since I couldn't concatenate my STRING to a VARIABLE the workaround was to look up the STRING name of the frame in _G which then also pointed to the frame?

Correct?
Yes.

Last edited by ravagernl : 05-13-13 at 12:55 PM.
  Reply With Quote
05-13-13, 10:26 PM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Jonisaurus View Post
And the CreateFrame arg2 creates a name as a global STRING in _G, but it also creates a global VARIABLE in _G, and both point to the same frame?
Technically, the contents of _G are not "global strings" -- they are table keys.

CreateFrame("Frame", "MyFrame") creates a frame (which is really just a table with special properties) and creates a global variable MyFrame pointing to that frame. If you want to hide that frame, you can either look it up directly with MyFrame:Hide() or -- if you like wasting time and being slow -- you can look it up in the _G table with _G["MyFrame"]:Hide().

The only reason you should ever use the _G table lookup method is if you're constructing the variable name dynamically, such as inside a loop like you're doing.

_G itself is a global variable, so _G["MyFrame"] costs one global lookup plus one table lookup, while MyFrame costs only one global lookup.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
05-15-13, 07:50 AM   #8
Jonisaurus
An Aku'mai Servant
 
Jonisaurus's Avatar
Join Date: Aug 2011
Posts: 35
Are table keys their own data type or do they belong to string, number etc.? Thanks for explaining.

_G itself is a global variable, so _G["MyFrame"] costs one global lookup plus one table lookup, while MyFrame costs only one global lookup.
Would something like
Lua Code:
  1. local _G = _G

be helpful to implement for performance reasons?

Also, is there any way to check the impact something like that has on the performance of my addon and the CPU?
  Reply With Quote
05-15-13, 08:53 AM   #9
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
Originally Posted by Jonisaurus View Post
Are table keys their own data type or do they belong to string, number etc.? Thanks for explaining.



Would something like
Lua Code:
  1. local _G = _G

be helpful to implement for performance reasons?

Also, is there any way to check the impact something like that has on the performance of my addon and the CPU?
If you have room for upvalues (there is a limit, don't worry it will tell you when you reach it :P) - yeah I don't see a problem having that on top of your lua file.
__________________
Profile: Curse | Wowhead
  Reply With Quote
05-15-13, 09:52 AM   #10
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Originally Posted by Jonisaurus View Post
Are table keys their own data type or do they belong to string, number etc.? Thanks for explaining.
Anything that evaluates to true can be a table key.

Originally Posted by lua-users.org
A key need not be a number, it can be a string, or for that matter, nearly any other Lua object (except for nil or 0/0).
  Reply With Quote
05-15-13, 03:05 PM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Jonisaurus View Post
Would something like
Lua Code:
  1. local _G = _G

be helpful to implement for performance reasons?
No, because you should not be doing things like _G.UnitName("target") in your code -- you should just be doing UnitName("target"), and upvaluing UnitName if you're calling it very frequently (eg. in an OnUpdate script, COMBAT_LOG_EVENT_UNFILTERED event handler, etc.).
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Concatenating a string+number to be an argument


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