Thread Tools Display Modes
12-17-12, 12:08 AM   #1
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Calling a local function from another local funtion

Hi all,

I'd like to ask why a code like this will produce exit with an error like unable to find global b():

Lua Code:
  1. local function a()
  2. -- code
  3.  
  4. end
  5.  
  6.  
  7. local function b()
  8. -- code
  9.  
  10. end
  11.  
  12.  
  13. local function c()
  14. -- code
  15.  
  16. b()
  17.  
  18. end

This because if I change my functions to local: RemGank_Validate_DB, RemGank_Check_Player, RemGank_Add_Player and RemGank_Record_Player

this doesn't work anymore:


Lua Code:
  1. -- code
  2.  
  3. local function RemGank_Record_Player(name, note)   
  4.  
  5.     if note == nil or note == "" then  note = default_note end
  6.  
  7.     RemGank_Validate_DB(name)
  8.  
  9.     RemGankDB[name]["name"] = name:lower()
  10.     RemGankDB[name]["desc"] = string.sub(note,1,25)
  11.     RemGankDB[name]["lastloc"] = GetZoneText() .. "/" .. GetSubZoneText() .. " - " .. date("%d.%m.%Y %H:%M:%S")
  12.     RemGankDB[name]["nrkill"] = ( RemGankDB[name]["nrkill"] + 1 )  
  13.    
  14.     print(string_format("%s: adding %s [ %s ] [ kills: %i ] ", prgname, name, note, RemGankDB[name]["nrkill"]))
  15.    
  16. end
  17.  
  18. local function RemGank_Validate_DB(name)
  19.     RemGankDB[name] = RemGankDB[name] or {}
  20.     RemGankDB[name]["name"] = RemGankDB[name]["name"] or {}
  21.     RemGankDB[name]["desc"] = RemGankDB[name]["desc"] or {}
  22.     RemGankDB[name]["lastloc"] = RemGankDB[name]["lastloc"] or {}
  23.     RemGankDB[name]["nrkill"] = RemGankDB[name]["nrkill"] or 0
  24. end
  25.  
  26. -- code


If I declare them not local everything works.

I'll attach the full code if someone wants to check it.

As usual thanks in advance to everyone.
Attached Files
File Type: zip Remgank-v0.9.zip (4.2 KB, 359 views)
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
12-17-12, 01:23 AM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Your example a/b/c code will work fine, because the "b" function is defined before you try to call it in the "c" function. Your real code will not work fine, because your "RemGank_Validate_DB" function is not defined before you try to call it in your "RemGank_Record_Player" function.

You have two options:

1. Define the functions in the proper order so that each one is defined before you try to call it:

Code:
local function A() print("A") end -- create this first
local function B() return A() end -- before you call it here
2. Define all of the locals first, and then set their values in whatever order:

Code:
local A, B

function B() return A() end
function A() print("A") end
However, if you only call "RemGank_Validate_DB" from "RemGank_Record_Player" you should just get rid of the whole "RemGank_Validate_DB" function, and just put its code directly in the "RemGank_Record_Player" function.

Better yet, you should just validate your DB once when your addon loads, instead of every time you add a record.
__________________
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
12-17-12, 01:06 PM   #3
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Hi Phanx,

As usual thanks for the reply.

Lua Code:
  1. function RemGank_Record_Player(name, note) 
  2.  
  3.     if note == nil or note == "" then  note = default_note end
  4.    
  5.     -- Define the new row in the array
  6.     RemGankDB[name] = RemGankDB[name] or {}
  7.    
  8.     -- not mandatory to be initialized anymore.
  9.     -- RemGankDB[name]["name"] = RemGankDB[name]["name"] or {}
  10.     -- RemGankDB[name]["desc"] = RemGankDB[name]["desc"] or {}
  11.     -- RemGankDB[name]["lastloc"] = RemGankDB[name]["lastloc"] or {}
  12.    
  13.     -- To prevent the math err on the sum of ( nil + 1 ) below
  14.     RemGankDB[name]["nrkill"] = RemGankDB[name]["nrkill"] or 0
  15.  
  16.     RemGankDB[name]["name"] = name:lower()
  17.     RemGankDB[name]["desc"] = string.sub(note,1,25)
  18.     RemGankDB[name]["lastloc"] = GetZoneText() .. "/" .. GetSubZoneText() .. " - " .. date("%d.%m.%Y %H:%M:%S")
  19.     RemGankDB[name]["nrkill"] = ( RemGankDB[name]["nrkill"] + 1 )  
  20.    
  21.     print(string_format("%s: adding %s [ %s ] [ kills: %i ] ", prgname, name, note, RemGankDB[name]["nrkill"]))
  22.    
  23. end


Studying better my code I finally realized that I don't need the commented out part.

The line 6 is mandatory as you explained me some messages ago :-) and the 14 is to prevent a math error when trying to add a nil + 1 few lines after.

Better yet, you should just validate your DB once when your addon loads, instead of every time you add a record.
This is the part I could not understand how to accomplish.
This because the only way I think I could do is something like :

Lua Code:
  1. if event == "ADDON_LOADED" and arg1 == "Remgank" then
  2.        
  3.         --- other code
  4.  
  5.         for name in pairs(RemGankDB) do
  6.             RemGankDB[name] = RemGankDB[name]
  7.         end
  8.     end

But I have to add the same 2 lines (6 and 14 of the first sample) in the RemGank_Record_Player to prevent an error when RemGankDB[name] is nil ( adding a new player not yet in the DB ) .

So I don't find any utility in use that for ... end in the ADDON_LOADED event.

I am sorry if this message is not so clear but it is not easy for me to explain better.

Thanks again for your time.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
12-17-12, 04:04 PM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
This literally does nothing:

Code:
for name in pairs(RemGankDB) do
    RemGankDB[name] = RemGankDB[name]
end
It just spends CPU cycles going through the database and saying "set this key to the same value it alread has". At the end of the loop absolutely nothing has actually been done.

If your database only contains name=data pairs, and not any other settings, then this is all the initialization you need to make sure it is defined as a table the first time your addon runs:

Code:
RemGankDB = RemGankDB or {}
Then, when adding a name, you will need to keep this check:

Code:
RemGankDB[name] = RemGankDB[name] or {}
It would not make sense to do anything with names at load because you do not know, in advance, the names of players who are going to kill you.
__________________
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 » Calling a local function from another local funtion

Thread Tools
Display Modes

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