View Single Post
09-19-14, 04:42 AM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
How a table looks compared with a frame

A frame is really just a table with some special properties. Anything you can do with a table, you can also do with a frame:

Code:
-- make a table:
local t = {}
-- add a key with a value:
t["cat"] = "meow"
-- add an indexed value:
table.insert(t, "Look, a value!")
-- add another indexed value:
table.insert(t, "Another value!")
-- sort the indexed values by alphabet:
table.sort(t)
-- print the indexed values in order:
for i = 1, #t do
   print(t)
end
-- print all the values (indexed and keyed):
for k, v in pairs(t) do
   print(k, "=", v)
end
-- remove all the values:
table.wipe(t)
All of the above still works if you change the first line to:

Code:
local t = CreateFrame("Frame")
However, there are some things you shouldn't do with a frame, or you might break it. For example, if you wipe a table (the last line in the example above) you will remove its special frame-ness, which is a special type of value called "userdata" and is stored under the numeric key 0 in the table:

Code:
local t = CreateFrame("Frame")
print(type(t[0])) -- prints "userdata"
If you remove that value, or overwrite it, manually, that will also remove the frame magic:

Code:
local t = CreateFrame("Frame")
t:SetParent(WorldFrame) -- this works
t[0] = "LOL I BROKE IT"
t:SetParent(UIParent) -- now it doesn't work
Now, you may be wondering how the frame still has a "SetParent" method even after you removed its frame-ness; that's because that (and other frame methods) are attached using a metatable, which is another special property, sort of like being a frame, except that you can give any table a metatable, whereas the frame userdata can't be added to an existing table -- it can only be created by creating a frame.

Technically "userdata" is a fancy way of saying "a pointer to something that only exists in the C code outside of the Lua scripting environment" since Lua is a scripting language running inside a program written in C (actually I think WoW is in C# but that doesn't matter for this demonstration) just like JavaScript is a scripting language running inside your web browser, or your web browser runs inside your operating system (probably Windows) etc.

Anyway, metatables are probably beyond the scope of what you'll be doing in the near future, but they're not actually that complicated, so if you're interested I can explain that a bit more.

------------------------------

What a Method realy does with a frame

The short answer: Nothing.

The long answer: A method is just a function, but it's defined in a special way so that it's attached to a table (maybe a frame, maybe some other kind of UI object, or maybe just a plain old table).

Code:
local WhatAnimalsDo = {
    ["cats"] = "chase lasers",
    ["dogs"] = "chase squirrels",
    ["goats"] = "jump on things",
}

function WhatAnimalsDo:Explain(who)
    local what = self[who]
    print("Did you know that", who, what, "?")
end
When you define a function as a method ("Explain") on a table ("WhatAnimalsDo") using a colon (":") then inside the function a variable named "self" magically exists. As long as you also call the method with a colon, then "self" refers to the table the method is defined on ("WhatAnimalsDo"). You could also write it this way:

Code:
function WhatAnimalsDo.Explain(self, who)
    local what = self[who]
    print("Did you know that", who, what, "?")
end
... but that's more typing, so who wants to do that? But it is helpful to understand that it's the same, so you can also understand why it won't work correctly if you call it like this:

Code:
WhatAnimalsDo.Explain("cats") -- note the dot!
... because you're only passing one value to the function, so it will be assigned to the variable "self", and the variable "who" won't have any value at all, and you'll get an error when you try to look up a value in "self" because you can only look up values in tables, and the string "cats" isn't a table.

But if you call it like this, it works:

Code:
WhatAnimalsDo:Explain("cats") -- colon!
... because Lua magically passes the object as the first value. It would also work if you passed the object explicitly and used dot notation:

Code:
WhatAnimalsDo.Explain(WhatAnimalsDo, "cats")
... but again, why type more than you have to?

So, as you can see, a method doesn't "do" anything with the table it's defined on, unless you do something with it inside the function. It's just a special way of writing functions that attach them to tables/frames/other objects, and "magically" pass references to the object.

------------------------------

What local variables do

Assuming you already know what a variable is, the "local" keyword just limits where a variable exists. If you write:

Code:
MyVariable = 5
... then your variable is global and any code from any addon can read its value, overwrite its value, or even delete it. If two addons write the same thing, then the second addon overwrites the first one's value, and only one copy of the variable exists, with the value the second addon gave it. This is generally not a desirable situation, and you should avoid creating any global variables unless you actually need them to be globals for a reason.

Code:
local MyVariable = 5
If that's at the very top of your file, then any code anywhere in that file can read from and write to MyVariable. If it's not at the top of the file, then only code written after it in the file can see it.

Code:
local function PrintMyVariable()
     print(MyVariable)
end

local MyVariable = 5

PrintMyVariable()
... will print "nil" to your chat frame, because the "PrintMyVariable" function can't see "MyVariable".

Code:
do
     local x = 10
     print(x)
end
print(x)
... will print "10" and "nil" because "x" only exists inside the block of code in between "do" and "end". This is called scoping -- local variables are visible to all lower scopes, but not to any higher scopes.

Code:
local x = 10
print(x)

do
    local x = x * 2
    print(x)
end

print(x)
... will print 10, 20, and 10 again. Inside the scope of the do/end block, the local "x" overwites the "x" from the higher scope, but outside of that scope, only the first "x" exists.

You can think of scopes like those Russian nesting dolls, made out of one-way glass. If you're in between dolls, you can see outward to see what's in all the bigger dolls, but you can't see inward to see what's in the smaller dolls.

Functions also create scopes, as do loops of all kinds (for, while, repeat), and basic control structures like if, elseif, and else.

As a general rule, you should always define your variable in the narrowest (or lowest, or the smallest doll) scope that's needed. This keeps your code readable, helps avoid unexpected conflicts if you use the same variable name in different scopes for different purposes, and avoids wasting memory by holding onto values that are no longer needed (since any variables that are local to a scope are effectively erased at the end of the scope).

------------------------------

how the .. "directory tree" is working. Like the basic markup of a file. Im missing some stuff like writing in html
There is no "basic markup" or "directory tree" in a Lua file. Unlike HTML, there are no required structures -- you don't need to wrap everything in an <html> tag, for example. You just write what you want.

If i guess right frames are created in .xml and "what stuff does" in the .lua so its a bit like .lua = .html, .xml = .css.
You can create frames in XML, but you shouldn't. It's ugly, verbose, a pain in the ass to work with, and totally unnecessary. (Also your analogy is a bit off; if you're using XML for frames and Lua only for scripts, then XML is like HTML and CSS -- what things look like -- and Lua is like JavaScript -- what things do.)

Rly annoying to lose the ability to learn something by your self just with the informations you get in the internet and to be honest. I would feel realy retarded if i try to write addons and just open threads on wowinterface for every thing i cant find a solution for.
I have no formal education in any kind of programming, even web programming which is what I do for a living. I've always just learned by looking at examples. I taught myself HTML about 20 years ago when I was in middle school by looking at the source code of existing web pages and figuring out how the code produced the result. I suspect this is why I'm so good at explaining things in simple terms, because in many cases I didn't actually learn the technical terms until after I'd already figured the basic concepts and was looking at documentation to clarify tricky points.

Sometimes my worse english is struggeling a bit. I definitly do understand it better than i speak (seems to be usuall if i compare it to .lua ) but ye.
Ich fühle mich genauso über mein Detusch.
__________________
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