11

I've found some places on the web saying that operators in Lua are overloadable but I can't seem to find any example.

Can someone provide an example of, say, overloading the + operator to work like the .. operator works for string concatenation?

EDIT 1: to Alexander Gladysh and RBerteig:
If operator overloading only works when both operands are the same type and changing this behavior wouldn't be easy, then how come the following code works? (I don't mean any offense, I just started learning this language):

printf = function(fmt, ...)
    io.write(string.format(fmt, ...))
end

Set = {}
Set.mt = {}    -- metatable for sets

function Set.new (t)
    local set = {}
    setmetatable(set, Set.mt)
    for _, l in ipairs(t) do set[l] = true end
    return set
end


function Set.union (a,b)
    -- THIS IS THE PART THAT MANAGES OPERATOR OVERLOADING WITH OPERANDS OF DIFFERENT TYPES
    -- if user built new set using: new_set = some_set + some_number
    if type(a) == "table" and type(b) == "number" then
        print("building set...")
        local mixedset = Set.new{}
        for k in pairs(a) do mixedset[k] = true end
        mixedset[b] = true
        return mixedset
    -- elseif user built new set using: new_set = some_number + some_set
    elseif type(b) == "table" and type(a) == "number" then
        print("building set...")
        local mixedset = Set.new{}
        for k in pairs(b) do mixedset[k] = true end
        mixedset[a] = true
        return mixedset
    end

    if getmetatable(a) ~= Set.mt or
        getmetatable(b) ~= Set.mt then
        error("attempt to 'add' a set with a non-set value that is also not a number", 2)
    end

    local res = Set.new{}
    for k in pairs(a) do res[k] = true end
    for k in pairs(b) do res[k] = true end
    return res
end


function Set.tostring (set)
    local s = "{"
    local sep = ""
    for e in pairs(set) do
        s = s .. sep .. e
        sep = ", "
    end
    return s .. "}"
end

function Set.print (s)
    print(Set.tostring(s))
end

s1 = Set.new{10, 20, 30, 50}
s2 = Set.new{30, 1}

Set.mt.__add = Set.union

-- now try to make a new set by unioning a set plus a number:
s3 = s1 + 8
Set.print(s3)  --> {1, 10, 20, 30, 50}
1
  • 1
    It is true for comparison operators - not regular operators. Overloading to add both a table and a string, for example, is perfectly valid. Commented May 12, 2010 at 17:06

2 Answers 2

14

The metatable function only works on tables, but you can use debug.metatable to set the strings metatable...

> mt = {}
> debug.setmetatable("",mt)
> mt.__add = function (op1, op2) return op1 .. op2 end
> ="foo"+"bar"
foobar
> 

Another approach is to use debug.getmetatable to augment the built-in string metatable (answering the question in the comment below):

~ e$ lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> debug.getmetatable("").__add = function (op1, op2) return op1 .. op2 end
> ="foo"+"bar"
foobar
> 
Sign up to request clarification or add additional context in comments.

14 Comments

@Pessimist: Note that, while it works, it is probably a bad practice to change the string metatable in this way. Do not adapt the language to your old habits — it is always more productive to change the habits instead in the long run.
Note that the example replaces the existing metatable for strings, which is (usually) the string module so that global lookups are not needed for most actions on strings. It would be possible to add the __add method to the existing metatable instead by using debug.getmetatable to retrieve it. As Alexander says, this is not necessarily a good idea to really do, however.
@Alexander Gladysh: thanks for the advice but I'm just trying to see what Lua is capable of. I like the concept of DSLs (domain-specific languages) so I will probably be abusing these features. :)
@DeadMG: You will get a security risk if you allow untrusted code to change metatables for non-table types.
For example, malicious code wouldb be able to change behaviour of otherwise-save "system-level" Lua code. That code may have legitimate access to the unsafe functions. Such attack does require some knowledge about the program internals, but is a risk nevertheless.
|
6

See the Metatables section of Lua Programming Manual and Metatables and Metamethods chapter of the Programming in Lua 2nd edition.

Note that for comparison operators operator overloading works only when both operand types are the same.

5 Comments

The point about operand type cannot be emphasized enough. This is different from quite a few other languages that support overloading. Changing it would not be easy, either.
Thanks for the links. Please see EDIT 1 above.
That is only true for comparison operators. It isn't true for generic operators. Your posted link is six years out of date.
@DeadMG: Um... you may be right. Some Lua 5.0 leftovers are left in my mind. Note that Lua Programming Manual link is still valid — it is for 5.1 manual. PiL link leads to outdated Lua 5.0 edition and may contain obsolete information.
@Pessimist: Please consider buying second edition then: inf.puc-rio.br/~roberto/pil2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.