LibMindReader is a mixin library (can also run 'not mixed in') that generates an AceConfigDialog-table from a variable. Running this table then allows the user to peek, poke and prod the variable in the following ways:
- The table structure is shown as a tree. Efforts have been done do avoid recursiveness due to tables linking each other.
- Selecting a table node in the tree shows an input box where the user can input some code and execute it as a method of that node.
- Selecting a number or a string shows an input box where the value can be viewed and edited. Editing is not available if the number or string is not a member of a known table.
- Selecting a function shows an execute button to execute the function. An inputbox is also provided to type in code to generate parameters for the call.
Because the parameters of a function can not be determined from within Lua the addon being debugged can provide LibMindReader with a tip through calling of :AddFtionTip(func, paramstring, ismethod) or :AddFtionTips(tiptable).
When building the AceConfig-node for the function LibMindReader will use paramstring to help the user.
The builds can be managed using a standalone addon called MindBrowser (not yet created)
I fail to see the purpose of this. Libraries should not be written if nobody is going to use them. Useless libraries will have to answer to my wrath eventually. Libraries that don't follow the same short project naming convention as the rest of the libraries will also have to answer to my wrath. And you used WowAddonStudio, you can't really get much more fail than that. I need a 'move to curseforge' moderator option.
Arrowmaster, things like this are useful for debugging weird shit IMO, i've had several instances where this sort of thing would have been useful to find out why a function isn't working properly or where things are in following a "what is self in this context" problem. Tho i got by with /dump, this would have been prefered.
Because the parameters of a function can not be determined from within Lua the addon being debugged can provide LibMindReader with a tip through calling of :AddFtionTip(func, paramstring, ismethod) or :AddFtionTips(tiptable).
So... this is basically something you expect addon authors to spend extra time and effort writing extra code to support only to avoid having to remember what other functions they wrote and what those do? That's what I'm getting from your description and the example on your project page... :confused:
So... this is basically something you expect addon authors to spend extra time and effort writing extra code to support only to avoid having to remember what other functions they wrote and what those do? That's what I'm getting from your description and the example on your project page... :confused:
Phanx, your worry is understandable, but anticipated:
1. you don't HAVE to do function tips. They just ease the debugging process by helping the addon dev remember what parameters a certain function/method needs.
2. The accompanying MindBrowser addon which I will write once BeneCast 10 is done will have the posibility of you pasting your whole source file in an editbox and MindBrowser will add function tips FOR YOU and spit it out in another editbox. How's that for convenience?
Is that the purpose of this? That's nothing like what the post or description describe it as from what I could tell.
Arrowmaster, I don't understand this sentence. But I can tell you this, as OrionShock mentioned, this is a developers tool (which is why it's in the "Development Tools" category.
It lets the developer inspect a variable without awkward slash commands.
I find it hard to believe ANY developer NOT wanting this library (still, it could happen :p).
That'd be a great addon as well. Sounds more like a suggestion for chatframe addons though. My backlog of "addons I'd like to code" is already clogged with:
- Finishing BeneCast 10
- Making MindBrowser (manage MindReader-builds and aid in generating function tips)
- Making BreadCrumbs (same lib+addon style development tool to be able to go back in a callstack and see the value of certain variables, using MindReader off course to visualize it)
- Maybe make a RDBMS-library for WoW. Reception in the "Addon Ideas" forum wasn't great though.
- Adding a "table printer' (name needs work :D) with tab-completion will either be at the end or after MindBrowser depending on how I feel my knowledge of the chatframe is.
Arrowmaster, I don't understand this sentence. But I can tell you this, as OrionShock mentioned, this is a developers tool (which is why it's in the "Development Tools" category.
It lets the developer inspect a variable without awkward slash commands.
I find it hard to believe ANY developer NOT wanting this library (still, it could happen :p).
While I am not opposed to developer tools, I personally find this library unneeded for any of the 12 or so addons in my development. /print and /run are more than enough sufficient tools for me.
I find it hard to believe ANY developer NOT wanting this library (still, it could happen :p).
Consider the following code:
local link
local function filter(msg)
link = msg:match("|Hitem:(%d+):") or msg:match("|H(%a+):") -- msg:match("|H([sqe][pun][ec][lsh][lta]n?t?):")
if link and db.item[link] or db[link] then
return true
end
end
ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL", filter)
ChatFrame_AddMessageEventFilter("CHAT_MSG_SAY", filter)
ChatFrame_AddMessageEventFilter("CHAT_MSG_YELL", filter)
ChatFrame_AddMessageEventFilter("CHAT_MSG_TEXT_EMOTE", filter)
That is the functional core of my addon Unlinked; the remainder of its 4kb code centers around a few simple toggle configuration options. Do you honestly find it so impossible to believe that I see no use for your debugging library here? If so, I suggest you work on broadening your horizons of belief. Even in my larger addons, I can tell you with complete certainty that I have never had any difficulty remembering, or ascertaining very quickly from reading my code, what the functions I wrote do, what functions they call, or what functions call them. There are already much simpler tools to accomplish what you're doing here. If it helps you, great, but don't expect that everyone else shares your narrow view of possibility.
I would blame my narrow view of disbelief upon the, apparently incorrect, assumption that people were blessed with the same faulty memory my brain is equipped with. As such I assumed (another nono of course) that this Lib would be widely accepted, praised and I would be welcomed into the WoWAce pantheon of dev-gods.
Now, with my dreams shattered, I am alone instead of many. Cast down from my fantasy into the barren truth of reality. I suppose I have to thank you, Arrowmaster and Phanx, for this.
Yet, this is not the first time this has happened. And according to Battlestar Galactica (reimagined series of course) lore 'all this has happened before, and it will happen again'. See you in the official thread of my next crackpott idea.
All kidding aside:
Okay, so not ALL devs will use this. Even if only one other than me uses it it will have been worth posting it here. Please don't slag an idea because you personally don't see yourself using it.
Adding to that:
I am a pretty verbose developer. I write my code with the intention that I may forget what I wrote where or what a certain var meant. So I put it in places I expect myself to look and I name my variables very descriptive. Regex-expressions have always been very 'chinese' to me (although I do comprehend their power I do not master it).
With that I invite anyone to overview my code and point out:
- glaring mistakes
- extreme inefficiencies
- things that can be done by using a certain, pre-existing, library
advice like 'write t instead of tablevar' won't help though.
1. You should not use a library for table recycling. This has been done in the past (See CompostLib), and has proven disastrous for addon debugging. What happens is that AddOnA uses a table from the library, later releases the table back into the library, but leaves dangling references to it. AddOnB then uses this recycled table, and experiences errors that AddOnA is causing by using the dangling referenec to the table (such as adding/removing entries to the table with tinsert).
This is impossible to debug because the table's origins would be totally unknown, addonB's code is perfect, but A isn't, but because of A, B is having errors. It's been tried, used, and proven to be a disaster. Remove table reycling from LibHandyHelper. Each addon should use its own local table recycling to contain possible coding errors.
We're talking safe coding practices here.
2. You have ugly code. Consider:
-- The table has an inline group that contains controls for doing stuff on the variable
local sg = hp:new();
sg.name = sname;
sg.type = 'group';
sg.order = 1;
sg.inline = true;
sg.args = hp:new();
n.args[s] = sg;
local label = hp:new();
label.name = 'String variable';
label.type = 'description';
label.order = 1;
sg.args.label = label;
Why not just do
local sg = {
name = sname,
type = "group",
order = 1,
inline = true,
args = {
[s] = sg,
label = {
name = "String Variable",
type = "description",
order = 1,
},
},
}
It's faster (to execute), cleaner to see, and if you really want to, you can still release these tables back to the recycling table pool later. As it is, your addon has zero intention of recycling these created nodes because you don't know if the calling addon will release it properly without dangling references.
And "s" is a table in your code, using tables as a key in the args table is disallowed by AceOptions table standards because it has to be parsable and printable by other AceOptions implementations such as AceConsole.
3.
-- what's this for anyway? isn't mr.embeds empty at this time??
for addon in pairs(mr.embeds) do
mr:Embed(addon)
end
You wrote a library without knowing what this does? It takes the existing addons that already embedded the library, and reembed them in case of library upgrades (newer version of the library in a second addon), by overwriting the old function references with the new references in the upgraded library.
4. I don't even want to comment on LibHandyHelper, it has so many useless functions that are 1-line function wrappers, if any calling addon code needed the functionality of say "UnitIsPartyPet" or "GetRaidPetOwnerID", they would have just called the actual functions directly, and skip the overhead of your 1-line function wrappers.
We call this the Alar syndrome (See the AlarLib, for being a library that contains 200 wrappers adding unnecessary overhead).
Libraries, being shared code, are primarily designed with efficiency and speed in mind, the function wrappers are against this philosophy. They might be handy to use, yes, but they are inefficient to use.
Particularly because your library doesn't even upvalue commonly accessed functions such as type, next, pairs by doing
local type, next, pairs = type, next, pairs
at the start of the file, to avoid global function lookups.
5.
do
local pool = setmetatable({},{__mode='k'})
hp.new = function()
local t = next(pool)
if t then
pool[t] = nil
return t
else
return {}
end
end
hp.del = function(t)
for k in pairs(t) do
t[k] = nil
end
pool[t] = true
end
end
You copied table recycling code, without considering the fact that you also need to setmetatable(t, nil) on a recycled table in the hp.del() function, or existing metatables in recycled tables will haunt you forever when another addon tries to use the table.
AceGUIWidget-TreeGroup didn't need to nil out metatables because it knows its own code doesn't set metatables on its tables, and nobody else outside the file can use the recycling functions.
Also,
for k in pairs(t) do
t[k] = nil
end
Can just be called as wipe(t) now in wow's lua, which is a lot faster.
6.
-- Version of table.getn that gets a count of ALL members
hp._CountMembers = function(Table)
local cnt = 0;
local k, v = next(Table);
while k ~= nil do
-- v is probably never nil in this case, but just to be sure...
if v ~= nil then
cnt = cnt + 1;
end
k, v = next(Table,k);
end
return cnt;
end
Are you aware that pairs() is a lot faster than next() ?
And that v cannot be nil so the check is redundant?
-- Version of table.getn that gets a count of ALL members
hp._CountMembers = function(Table)
local cnt = 0;
for k, v in pairs(Table) do
cnt = cnt + 1;
end
return cnt;
end
7.
-- Like the isnull function in SQL, returns a substitute value if first value is nil
hp._isnil = function(value, repl)
if value == nil then
return repl;
else
return value;
end
end
I wanted to choke on this one, because
n = isnil(a, b)
would be identical to
n = a == nil and b or a
assuming b is not the value false or nil, which in 99.99% of use cases, b won't be either of them.
---------
There, you wanted critique, I gave it. Summary:
- LibMindReader could be useful, but the code is ugly, and the use of recycled tables will bite you at the end of the day if some other addon developer fails to destroy dangling references.
- LibHandyHelper is primarily useless. While we welcome any developer to join the wowace community, we do want the stuff we host to be good code, and if it isn't good code, you'll hear no end of it. I only looked in it for about 3 minutes, If I tried harder, I'll find more issues. The code shows little understanding of Lua intrinsics, and short circuit evaluation.
Hey can this lib mindread whats going on in the old AceHook-2.1 lib? Because that would be awesome. That is the kind of code I would love to see a lib for that lets you figure out whats going on. Not that you don't KNOW whats going on ... hooking of stuff ... its just that you cannot actually simulate whats going on in your brain because the code recalls itself with shifting paramaters over and over again till you lose track by the 5th time you flow through a particular function yet again. It is like someone liked function overloading in C++ (and who would not) then decided what they need to do in lua is take all the overloaded functions and shove them into one function instead of just splitting them out into multiple functions.
I like to pick on this code because I think its a good candidate for a "Lua Tricks" book and therefore unsuitable as production code.
PS: I am sorry AceHook-2.1, it's just that you are so easy to pick on...;-p
One disclaimer though. I do not intend (not since the lib was officially rejected by you anyway :p) to publish my 'HandyHelper'-lib).
1. ok, I will move the table recycling out of the lib. I see why it'd be A Bad Idea.
2. I'll conceed to overusing the new()-table recycling ftion there. My reasoning was that, while I wasn't going to release the table I might still be using a recycled one instead of creating another new record. I'll change that.
The 'using a table as an index' is actually a bug you found! That was supposed to be 'sname' :D. I know I should avoid using tables as indices. Which is also why I convert the tables to their internal IDs first whenever I need to keep track of which table was used where (mostly in the avoiding cross-links throughout the tree).
3. Well since I "came onboard" WoWAce after the big move to Curse all the documentation is scattered all over. I found a lot of help on http://old.wowace.com, but if a decent "how to make a library and what it all does" exists I haven't found it. Plus one learns a lot from viewing other ppl's code.
Now, I'm no fool, I figured it was for some upgrading purpose seeing as how up top we find
mr.embeds = mr.embeds or {} -- what objects embed this lib
but I didn't wanna go ahead and make stupid assumptions. Simply adding it seemed the smartest thing to do.
4. Again, LibHandyHelper needs work. Your suggestions are valued. The wrapper functions are not used and are an ugly heritage of the old BeneCast. I really just wanted to get rid of them (I think BeneCast 10 uses only one or two of them and after I threw those out the wrappers were gonna get the boot (if that reassures you :)).
5. Since I don't use metatables (I do know what they are in any case, the matter is just a bit too complex for me at my current state of Lua-knowledge to implement) and I intend to move the recycling functions to my own addons this pitfall is avoided. Thanks for the warning in any case...
And as for wipe... nice
6. I thought next() was faster so I went with that. I'll use pairs() where possible. The check on nil is a relic from before I explicitly found it said in the Lua docs that setting to nil = deleting.
Follow Up Question: If I loop through a table w pairs() and I delete (set to nil) a member will the iterator mess up or properly hand me the next member as if I hadn't deleted anything?
7. I don't agree on the uselessness of isnil. It adds readability to code that would be needlessly obfuscated (for my feeble brain that is) in the places that I employ it.
----------------
Overall my aim is to eventually attain the standards that are set by who I hope to be allowed to call 'peers' (even if merely someday). With that, those tips are golden. Even if you couldn't resist adding every foul word that is used for describing less than optimal code. I'm actually a programmer IRL as well, but in other languages of course. I have had less time then I'd have liked to get to know the "Lua intrinsics". I DO know short circuit evaluation and I use it liberally unless, again, it inhibits readability. I'd rather have 4 lines of code that makes sense at a glance than 2 that requires 10 seconds of wondering what the hell it does.
- Glad you see a future for LibMindReader. I'll continue polishing it until you one day recommend it to a fellow dev!
- LibHandyHelper... well, it's a bit Leeroy-ish I know. But the table copy and searching functions have proven quite the timesaver and helped keeping code readable.
Hey can this lib mindread whats going on in the old AceHook-2.1 lib? Because that would be awesome. That is the kind of code I would love to see a lib for that lets you figure out whats going on. Not that you don't KNOW whats going on ... hooking of stuff ... its just that you cannot actually simulate whats going on in your brain because the code recalls itself with shifting paramaters over and over again till you lose track by the 5th time you flow through a particular function yet again. It is like someone liked function overloading in C++ (and who would not) then decided what they need to do in lua is take all the overloaded functions and shove them into one function instead of just splitting them out into multiple functions.
I like to pick on this code because I think its a good candidate for a "Lua Tricks" book and therefore unsuitable as production code.
PS: I am sorry AceHook-2.1, it's just that you are so easy to pick on...;-p
Well, my BreadCrumbs idea could help with that. But you'll have to add the crumbs to a local version of AceHook yourself. BreadCrumbs will then allow you to track the path the code has made throughout the addon by tracking the crumbs it dropped.
I just made MindReader first since I need it the most.
Follow Up Question: If I loop through a table w pairs() and I delete (set to nil) a member will the iterator mess up or properly hand me the next member as if I hadn't deleted anything?
You may safely delete entries that have already been iterated over (plus the current key being iterated on) when using pairs(). However, if you delete any key that hasn't been iterated over yet, or add a new key, you will get undefined behavior, and the code will choke/crash.
Has wipe(t) been introduced in 3.0 ? I didn't notice it in the UI concise change post.
Yes. It is added in 3.0, usable in both secure header code and non-secure code. wipe(t) will completely wipe out the contents of a table non-recursively (remove all key-value pairs). Any attached metatable is not affected.
Hmm, then i can replace non-recursive calls to my _ClearTable() function with wipe() instead. No other tablefunctions in there that are redundant? :p (sorry for using you as a question target).
BTW: After congesting all this input and applying it to MindReader and BeneCast AND once BeneCast has reached a stage where I am satisfied with it's stability I'll ask for some advice again.
I AM also glad to hear that my shortnamed-shortcut-locals to certain long-named globals are a sound idea performancewise.
Just realized a glaring nono in my code. I often use a var called type (to contain the type of a spell or buff, like 'hot' and 'rez' and such). Naturally, this'll block the usage of the type() Lua-function...
My fault for not prefixing my vars like I'm used to in my day-to-day programming.
Just realized a glaring nono in my code. I often use a var called type (to contain the type of a spell or buff, like 'hot' and 'rez' and such). Naturally, this'll block the usage of the type() Lua-function...
1) Get a real editor that hilites syntax, and specifically hilites lua key words, and wow api names as well. Make the color obviously different from your standard text.
2) It is only a problem if you also try to use the blocked function inside the blocked scope. However it is just horribad coding in general as you just created sample code someone may reuse incorrectly to block the function globally. Your instinct to not do that is correct.
3) My comment about the old AceHook code was to illustrate the flaw with all this. The point is not that the code needs new functions to somehow magically make it better. The point is bad code needs a rewrite. See the Ace3 version for a rewrite in this case.
LibMindReader is a mixin library (can also run 'not mixed in') that generates an AceConfigDialog-table from a variable. Running this table then allows the user to peek, poke and prod the variable in the following ways:
- The table structure is shown as a tree. Efforts have been done do avoid recursiveness due to tables linking each other.
- Selecting a table node in the tree shows an input box where the user can input some code and execute it as a method of that node.
- Selecting a number or a string shows an input box where the value can be viewed and edited. Editing is not available if the number or string is not a member of a known table.
- Selecting a function shows an execute button to execute the function. An inputbox is also provided to type in code to generate parameters for the call.
Because the parameters of a function can not be determined from within Lua the addon being debugged can provide LibMindReader with a tip through calling of :AddFtionTip(func, paramstring, ismethod) or :AddFtionTips(tiptable).
When building the AceConfig-node for the function LibMindReader will use paramstring to help the user.
The builds can be managed using a standalone addon called MindBrowser (not yet created)
See also http://www.wowace.com/projects/mindreader/pages/usage/
So... this is basically something you expect addon authors to spend extra time and effort writing extra code to support only to avoid having to remember what other functions they wrote and what those do? That's what I'm getting from your description and the example on your project page... :confused:
/print Prat.<tab through fields>
That'd be spiffy.
Phanx, your worry is understandable, but anticipated:
1. you don't HAVE to do function tips. They just ease the debugging process by helping the addon dev remember what parameters a certain function/method needs.
2. The accompanying MindBrowser addon which I will write once BeneCast 10 is done will have the posibility of you pasting your whole source file in an editbox and MindBrowser will add function tips FOR YOU and spit it out in another editbox. How's that for convenience?
Arrowmaster, I don't understand this sentence. But I can tell you this, as OrionShock mentioned, this is a developers tool (which is why it's in the "Development Tools" category.
It lets the developer inspect a variable without awkward slash commands.
I find it hard to believe ANY developer NOT wanting this library (still, it could happen :p).
That'd be a great addon as well. Sounds more like a suggestion for chatframe addons though. My backlog of "addons I'd like to code" is already clogged with:
- Finishing BeneCast 10
- Making MindBrowser (manage MindReader-builds and aid in generating function tips)
- Making BreadCrumbs (same lib+addon style development tool to be able to go back in a callstack and see the value of certain variables, using MindReader off course to visualize it)
- Maybe make a RDBMS-library for WoW. Reception in the "Addon Ideas" forum wasn't great though.
- Adding a "table printer' (name needs work :D) with tab-completion will either be at the end or after MindBrowser depending on how I feel my knowledge of the chatframe is.
While I am not opposed to developer tools, I personally find this library unneeded for any of the 12 or so addons in my development. /print and /run are more than enough sufficient tools for me.
Consider the following code:
That is the functional core of my addon Unlinked; the remainder of its 4kb code centers around a few simple toggle configuration options. Do you honestly find it so impossible to believe that I see no use for your debugging library here? If so, I suggest you work on broadening your horizons of belief. Even in my larger addons, I can tell you with complete certainty that I have never had any difficulty remembering, or ascertaining very quickly from reading my code, what the functions I wrote do, what functions they call, or what functions call them. There are already much simpler tools to accomplish what you're doing here. If it helps you, great, but don't expect that everyone else shares your narrow view of possibility.
Now, with my dreams shattered, I am alone instead of many. Cast down from my fantasy into the barren truth of reality. I suppose I have to thank you, Arrowmaster and Phanx, for this.
Yet, this is not the first time this has happened. And according to Battlestar Galactica (reimagined series of course) lore 'all this has happened before, and it will happen again'. See you in the official thread of my next crackpott idea.
All kidding aside:
Okay, so not ALL devs will use this. Even if only one other than me uses it it will have been worth posting it here. Please don't slag an idea because you personally don't see yourself using it.
Adding to that:
I am a pretty verbose developer. I write my code with the intention that I may forget what I wrote where or what a certain var meant. So I put it in places I expect myself to look and I name my variables very descriptive. Regex-expressions have always been very 'chinese' to me (although I do comprehend their power I do not master it).
With that I invite anyone to overview my code and point out:
- glaring mistakes
- extreme inefficiencies
- things that can be done by using a certain, pre-existing, library
advice like 'write t instead of tablevar' won't help though.
This is impossible to debug because the table's origins would be totally unknown, addonB's code is perfect, but A isn't, but because of A, B is having errors. It's been tried, used, and proven to be a disaster. Remove table reycling from LibHandyHelper. Each addon should use its own local table recycling to contain possible coding errors.
We're talking safe coding practices here.
2. You have ugly code. Consider:
Why not just do
It's faster (to execute), cleaner to see, and if you really want to, you can still release these tables back to the recycling table pool later. As it is, your addon has zero intention of recycling these created nodes because you don't know if the calling addon will release it properly without dangling references.
And "s" is a table in your code, using tables as a key in the args table is disallowed by AceOptions table standards because it has to be parsable and printable by other AceOptions implementations such as AceConsole.
3.
You wrote a library without knowing what this does? It takes the existing addons that already embedded the library, and reembed them in case of library upgrades (newer version of the library in a second addon), by overwriting the old function references with the new references in the upgraded library.
4. I don't even want to comment on LibHandyHelper, it has so many useless functions that are 1-line function wrappers, if any calling addon code needed the functionality of say "UnitIsPartyPet" or "GetRaidPetOwnerID", they would have just called the actual functions directly, and skip the overhead of your 1-line function wrappers.
We call this the Alar syndrome (See the AlarLib, for being a library that contains 200 wrappers adding unnecessary overhead).
Libraries, being shared code, are primarily designed with efficiency and speed in mind, the function wrappers are against this philosophy. They might be handy to use, yes, but they are inefficient to use.
Particularly because your library doesn't even upvalue commonly accessed functions such as type, next, pairs by doing
at the start of the file, to avoid global function lookups.
5.
You copied table recycling code, without considering the fact that you also need to setmetatable(t, nil) on a recycled table in the hp.del() function, or existing metatables in recycled tables will haunt you forever when another addon tries to use the table.
AceGUIWidget-TreeGroup didn't need to nil out metatables because it knows its own code doesn't set metatables on its tables, and nobody else outside the file can use the recycling functions.
Also,
Can just be called as wipe(t) now in wow's lua, which is a lot faster.
6.
Are you aware that pairs() is a lot faster than next() ?
And that v cannot be nil so the check is redundant?
7.
I wanted to choke on this one, because
n = isnil(a, b)
would be identical to
n = a == nil and b or a
assuming b is not the value false or nil, which in 99.99% of use cases, b won't be either of them.
---------
There, you wanted critique, I gave it. Summary:
- LibMindReader could be useful, but the code is ugly, and the use of recycled tables will bite you at the end of the day if some other addon developer fails to destroy dangling references.
- LibHandyHelper is primarily useless. While we welcome any developer to join the wowace community, we do want the stuff we host to be good code, and if it isn't good code, you'll hear no end of it. I only looked in it for about 3 minutes, If I tried harder, I'll find more issues. The code shows little understanding of Lua intrinsics, and short circuit evaluation.
I like to pick on this code because I think its a good candidate for a "Lua Tricks" book and therefore unsuitable as production code.
PS: I am sorry AceHook-2.1, it's just that you are so easy to pick on...;-p
1. ok, I will move the table recycling out of the lib. I see why it'd be A Bad Idea.
2. I'll conceed to overusing the new()-table recycling ftion there. My reasoning was that, while I wasn't going to release the table I might still be using a recycled one instead of creating another new record. I'll change that.
The 'using a table as an index' is actually a bug you found! That was supposed to be 'sname' :D. I know I should avoid using tables as indices. Which is also why I convert the tables to their internal IDs first whenever I need to keep track of which table was used where (mostly in the avoiding cross-links throughout the tree).
3. Well since I "came onboard" WoWAce after the big move to Curse all the documentation is scattered all over. I found a lot of help on http://old.wowace.com, but if a decent "how to make a library and what it all does" exists I haven't found it. Plus one learns a lot from viewing other ppl's code.
Now, I'm no fool, I figured it was for some upgrading purpose seeing as how up top we find
mr.embeds = mr.embeds or {} -- what objects embed this lib
but I didn't wanna go ahead and make stupid assumptions. Simply adding it seemed the smartest thing to do.
4. Again, LibHandyHelper needs work. Your suggestions are valued. The wrapper functions are not used and are an ugly heritage of the old BeneCast. I really just wanted to get rid of them (I think BeneCast 10 uses only one or two of them and after I threw those out the wrappers were gonna get the boot (if that reassures you :)).
5. Since I don't use metatables (I do know what they are in any case, the matter is just a bit too complex for me at my current state of Lua-knowledge to implement) and I intend to move the recycling functions to my own addons this pitfall is avoided. Thanks for the warning in any case...
And as for wipe... nice
6. I thought next() was faster so I went with that. I'll use pairs() where possible. The check on nil is a relic from before I explicitly found it said in the Lua docs that setting to nil = deleting.
Follow Up Question: If I loop through a table w pairs() and I delete (set to nil) a member will the iterator mess up or properly hand me the next member as if I hadn't deleted anything?
7. I don't agree on the uselessness of isnil. It adds readability to code that would be needlessly obfuscated (for my feeble brain that is) in the places that I employ it.
----------------
Overall my aim is to eventually attain the standards that are set by who I hope to be allowed to call 'peers' (even if merely someday). With that, those tips are golden. Even if you couldn't resist adding every foul word that is used for describing less than optimal code. I'm actually a programmer IRL as well, but in other languages of course. I have had less time then I'd have liked to get to know the "Lua intrinsics". I DO know short circuit evaluation and I use it liberally unless, again, it inhibits readability. I'd rather have 4 lines of code that makes sense at a glance than 2 that requires 10 seconds of wondering what the hell it does.
- Glad you see a future for LibMindReader. I'll continue polishing it until you one day recommend it to a fellow dev!
- LibHandyHelper... well, it's a bit Leeroy-ish I know. But the table copy and searching functions have proven quite the timesaver and helped keeping code readable.
Well, my BreadCrumbs idea could help with that. But you'll have to add the crumbs to a local version of AceHook yourself. BreadCrumbs will then allow you to track the path the code has made throughout the addon by tracking the crumbs it dropped.
I just made MindReader first since I need it the most.
You may safely delete entries that have already been iterated over (plus the current key being iterated on) when using pairs(). However, if you delete any key that hasn't been iterated over yet, or add a new key, you will get undefined behavior, and the code will choke/crash.
Has wipe(t) been introduced in 3.0 ? I didn't notice it in the UI concise change post.
Yes. It is added in 3.0, usable in both secure header code and non-secure code. wipe(t) will completely wipe out the contents of a table non-recursively (remove all key-value pairs). Any attached metatable is not affected.
BTW: After congesting all this input and applying it to MindReader and BeneCast AND once BeneCast has reached a stage where I am satisfied with it's stability I'll ask for some advice again.
I AM also glad to hear that my shortnamed-shortcut-locals to certain long-named globals are a sound idea performancewise.
My fault for not prefixing my vars like I'm used to in my day-to-day programming.
1) Get a real editor that hilites syntax, and specifically hilites lua key words, and wow api names as well. Make the color obviously different from your standard text.
2) It is only a problem if you also try to use the blocked function inside the blocked scope. However it is just horribad coding in general as you just created sample code someone may reuse incorrectly to block the function globally. Your instinct to not do that is correct.
3) My comment about the old AceHook code was to illustrate the flaw with all this. The point is not that the code needs new functions to somehow magically make it better. The point is bad code needs a rewrite. See the Ace3 version for a rewrite in this case.