CSci 450/503: Programming Languages
Lua Metatables

H. Conrad Cunningham

5 October 2016

Acknowledgements: These slides are adapted from slide set 10 for the course Programming in Lua created by Fabio Mascarenhas, Federal University of Rio de Janeiro, Brazil. It was presented at Nankai University, P. R. China, in July 2013.

Advisory: The HTML version of this document may require use of a browser that supports the display of MathML. A good choice as of September 2016 is a recent version of Firefox from Mozilla.

LUA METATABLES

Metatable

A metatable modifies behavior of another table

Scope of Metatables

Metamethods (1)

Metamethods (2)

Complex Number Example

Augment earlier complex number module with operations:

Sharing a Metatable

Overloading + with __add (1)

Overloading + with __add (2)

Arithmetic Resolution (1)

Arithmetic Resolution (2)

Arithmetic Resolution (3)

Equality

Overloading # and tostring

Relational Operations (1)

Relational Operations (2)

    local function le(c1, c2)
        if not is_complex(c1) then 
            return (c1 <= c2.real) and (c2.im >= 0)
        end 
        if not is_complex(c2) then 
            return (c1.real <= c2) and (c2.im <= 0) 
        end 
        return (c1.real <= c2.real) and (c1.im <= c2.im)
    end
    
    mt.__le = le
            
    local function lt(c1, c2) 
        return c1 <= c2 and not (c2 <= c1) 
    end

    mt.__lt = lt 

Using __index and __newindex

A Counting Proxy

    local mt = {}                        > proxy = require "proxy" 
                                         > t = proxy.track({}) 
    function mt.__index(t, k)            > t.foo = 5 
        t.__READS = t.__READS + 1        > print(t.foo)
        return t.__TABLE[k]              5 
    end                                  > t.foo = 2 
                                         > print(t.__READS, t.__WRITES)
    function mt.__newindex(t, k, v)      1       2 
        t.__WRITES = t.__WRITES + 1 
        t.__TABLE[k] = v 
    end 

    local function track(t) 
        local proxy = { __TABLE = t, __READS = 0, __WRITES = 0} 
        return setmetatable(proxy, mt) 
    end 

    return { track = track } 

Quiz

We can try to work around the limitation of __eq so we can have complex.new(2,0) == 2 by making complex.new return a real if the imaginary part is 0.

Which operations will continue to work with this change, and which will not work anymore?

Quiz Solution

We try to work around the limitation of __eq so we can have complex.new(2,0) == 2 by making complex.new return a real if the imaginary part is 0.

Which operations will continue to work with this change, and which will not work anymore?

It breaks #.