User:Deco Da Man

From GMod Wiki

Revision as of 21:37, 14 April 2009 by Deco Da Man (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

´'`\_(ò_Ó)_/´'` Tutorial storage (I'll make it a wikipage later):

This thread is supported by the Group For Less "LOL I COPYD FROM WIKI IT NOT WORK HALP PLES" And More "And x equals y plus z, old chaps.".

Note: I request an Lua Theory or Tutorial sub-forum :)

What are metatables?

If you aren't too up-to-date with the latest Jargon and Paradigms, the following explanation from the Lua Manual won't make much sense.

From the Lua Reference Manual: "Every value in Lua can have a metatable. This metatable is an ordinary Lua table that defines the behavior of the original value under certain special operations. You can change several aspects of the behavior of operations over a value by setting specific fields in its metatable."

So, I'm going to explain it.

I'm assuming you understand tables and how indexing (getting and setting) works. In a sequential form it'll be like this:

Well you are wrong, dear friend. WRONG! Let me explain... If the value is not found, Lua searches for a metatable. This metatable is a secret thingy in the background that is a last resort. If Lua doesn't know how to do something with an object, it will give the object's metatable a chance to help it.

Now, let's have some code:

 
myTable = {
    a = 1,
    b = 2,
}
myMetaTable = {}
function myMetaTable.__index(the_table, the_key)
    print(the_table, the_key)
    return 666
end
setmetatable(myTable, myMetaTable)
 

Now, let's say I went "print(MyTable.a)". Lua would search the table, find it, say "WHOOP" and return 1, cause that's what the table contains! Durr! Now let's say I went "print(MyTable.c)" Lua would search the table, not find it, say "OH SHIT" and ask the metatable (if it has one, otherwise it would return nil (durr)). Now, the metatable function __index is what Lua calls. 'the_table' argument is the table that's been indexed and 'the_key' is the key that's trying to get read. You can do WHATEVER YOU WANT in this function. The value that you return is what the indexing function returns. In the end, Lua would print the table, the key and the value! :O

I hope you understand the BASICS of it.

But, that's pretty useless. I can do that with a function!

I just used __index to show you the BASICS of metatables, there's much, MUCH more! :D

Imagine you wanted to do this:

 
MyTable = setmetatable({1,2,3}, MyMetaTable) -- setmetatable returns the first argument after setting it's metatable
print(MyTable(2)) -- prints 2  4  6
 

That's impossible! You can't call a table!

But you can! If you set the __call field of it's metatable, you can call it like a function! :O So, it might look something like:

 
function MyMetaTable.__call(the_table, an_argument)
    local new_table = {}
    for i,v in ipairs(the_table) do
        new_table[i] = v*an_argument
    end
    return unpack(new_table)
end
 

And BAM! You can call the table! :O

WOAH! What else can I do with this?

HEAPS! :D Including operators! For example:

 
Table1 = setmetatable({66,55}, MyMetaTable)
Table2 = setmetatable({33,99}, MyMetaTable)
for i,v in ipairs( Table1 + Table2 ) do
    print(i, v)
end
--[[ prints:
    1    66
    2    55
    3    33
    4    99
]]
 

Huh? Adding tables? What is this madness?

Madness? This... is... METATABLES! Metatables, my friend! By setting the __add field of an object's metatable, if Lua doesn't know how to add it, it will ask the metatable! The code I used:

 
function MyMetaTable.__add(the_table, the_other_table)
    local new_table = {}
    local count = 0
    for i,v in ipairs(the_table) do
        count = count+1
        new_table[count] = v
    end
    for i,v in ipairs(the_other_table) do
        count = count+1
        new_table[count] = v
    end
    return new_table
end
 

WOAHLY! But wait, what if you are adding two different objects, and both have __add?

Lua is smart ;) It will first check the left one, if it doesn't have an _add, it will go to the right one :D

Neat! What else can I do?

HEAPS! Here's a list. metamethod(arguments): explanation.

a > b is equivalent to b < a.

a >= b is equivalent to b <= a. Note that, in the absence of a "le" metamethod, Lua tries the "lt", assuming that a <= b is equivalent to not (b < a).

(Slightly copy'n'pasta from the manual, edited alot.)

This is so cool! But what are they usful for in application?

Alot!

Take memorising tables!

Huh?

Imagine you had a function that was VERY intense, called VeryIntenseFunction. Let's say the user enters numbers, and you want to give the answer to the user using VeryIntenseFunction. Let's say it could take a few minutes to work out the answer, but the user needs it quickly! Well, at first, you are stuffed. It needs to be worked out. But, if the user enters, let's say, '5' many times. Why work it out twice? Why not just store the answer? Well, that's what memorising tables are :D

It looks like this:

 
function VeryIntenseFunction(n)
    for i = 1,9000 do
        n = n+math.random(1, 9000)/10-math.random(1,1000)
    end
    for i = 1,9000 do
        n = n*0.1*10*0.1*10*0.1*10*0.1*10*0.1*10
    end
    return n
end
 
local MyMetaTable = {
    __index = function(object, key)
        local n = VeryIntenseFunction(key)
        object[key] = n
        return n
    end
}
 

That's the base of a memorizing table. The first time the user enters '5', it'll have to work it out. But the second time, it will just get it from the storage! If you remember from earlier, I said that Lua only calls metamethods if it can't figure it out for itself. So what we do, is store the computed value in the table. The metamethod is only called if you want a value that hasn't been worked out yet! It's a memory! Neat, huh?

Very neat! But I've tried to set up a memorising table, and failed horribly :(

Here ya go:

 
-- Setup
local MyMetaTable = {
    __index = function(object, key)
        local n = --the_value
        object[key] = n
        return n
    end
}
-- Usage
MyTable = setmetatable({}, MyMetaTable)
print(MyTable[1]) -- SLLLOOOOW
print(MyTable[2]) -- SLLLOOOOW
print(MyTable[1]) -- ZOOOOOOOM
 

Give me an example of an awesome-super-epic-meta-table-that-will-solve-all-my-coding-problems!

The super-epic-...-table is up to YOU to make! But a simple example class will come soon.

I WANT MORE :(

MORE WILL COME!

By the way, why are they called metatables?

Cause meta means data about data! :D

Well, at least Wikipedia says so.

That means if you set the metatable of a metatable, it's a metametatable or, data about data about data.

And if you set the metatable of a metatable of a metatable...

SHUT UP ALREADY!

Ok then... :(



I hope you enjoyed my tutorial, and learnt something! :eng101:

I did!

Good!

Bye!

Good bye!

smartass...

I'm still here!

OH! Opps...

...

Personal tools
Namespaces
Variants
Actions
Navigation
Lua Scripting
Functions
Hooks
Toolbox