metatables and the s:len() shorthand syntax

Post Reply
Caled
Posts: 403
Joined: Thu Apr 09, 2009 4:45 am

metatables and the s:len() shorthand syntax

Post by Caled »

The quote at the bottom of the post is from the official lua reference manual at lua.org
I believe that it is possible, through the use of meta tables, to define shorthand syntax for referring to table values. I am interested in this because I have begun to declare by functions inside tables rather than the global space, and also to use larger and larger tables for other values. This has a lot of advantages, but also the disadvantage of requiring extra typing while coding, and also less readability.
The string library provides all its functions inside the table string. It also sets a metatable for strings where the __index field points to the string table. Therefore, you can use the string functions in object-oriented style. For instance, string.byte(s, i) can be written as s:byte(i).
I like that. I want to write functions that have similarly 'nice' shorthand alternative syntaxes.
For example:
function av.prompt.set(t, v)
--the script
end
Can I set it up so that I can call the above function with:
hp:set(4353)
?

The lua reference manual is good, but I can't figure out how to use metatables from the examples it gives.
Code: [show] | [select all] lua
"index": The indexing access table[key].

     function gettable_event (table, key)
       local h
       if type(table) == "table" then
         local v = rawget(table, key)
         if v ~= nil then return v end
         h = metatable(table).__index
         if h == nil then return nil end
       else
         h = metatable(table).__index
         if h == nil then
           error(···)
         end
       end
       if type(h) == "function" then
         return (h(table, key))     -- call the handler
       else return h[key]           -- or repeat operation on it
       end
     end
    * "newindex": The indexing assignment table[key] = value.

           function settable_event (table, key, value)
             local h
             if type(table) == "table" then
               local v = rawget(table, key)
               if v ~= nil then rawset(table, key, value); return end
               h = metatable(table).__newindex
               if h == nil then rawset(table, key, value); return end
             else
               h = metatable(table).__newindex
               if h == nil then
                 error(···)
               end
             end
             if type(h) == "function" then
               h(table, key,value)           -- call the handler
             else h[key] = value             -- or repeat operation on it
             end
           end

    * "call": called when Lua calls a value.

           function function_event (func, ...)
             if type(func) == "function" then
               return func(...)   -- primitive call
             else
               local h = metatable(func).__call
               if h then
                 return h(func, ...)
               else
                 error(···)
               end
             end
           end



User avatar
tsuujin
Posts: 695
Joined: Fri Feb 26, 2010 12:59 am
Location: California
Contact:

Re: metatables and the s:len() shorthand syntax

Post by tsuujin »

the ":" operator functions in exactly the same way as the "." operator, except that it automatically passes the calling item as the first argument to the function.

think about it this way:
s:len()
actually just redirects to
string.len(s)

So, when they refer to treating a table as an object (as in Object Oriented Programming) what they really mean is that you can store a function in a table and call it, allowing the function to access other table data. It's not true OOP, but closer to C's psudo-OOP.

In order to do what you want, you need to define "hp" as a table, then declare a table element as the function "set".
Code: [show] | [select all] lua
hp = {}
hp.value = 0

function hp:set(v)
    self.value = 0
end

function hp:get()
    return self.value
end

hp:set(500)
echo(hp:get())
when you call either set or get using the ":" operator you're actually just passing the "hp" table as the first argument and referencing it as "self". You could just as easily use hp.value = v, but the syntax of using self is already familiar to many coders.

Post Reply