views:

404

answers:

2
+8  A: 

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
> 
Doug Currie
@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.
Alexander Gladysh
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.
RBerteig
@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. :)
Pessimist
@RBerteig: can you show me (maybe by posting another answer) how your code would be different from Alexander's? I'm not sure what you mean by "existing metatable" - is that the instance's metatable instead of the "string" metatable?
Pessimist
It's legit to change any metatable from the C API in regular code. I'm not wholly sure why setmetatable has that restriction from Lua.Basically, pessimist, you would use debug.getmetatable("somestring").add = function(...). That way, you will preserve the original __index behaviour.
DeadMG
@DeadMG: would you be kind as to show be an example code using getmetatable? I'm confused about how to use it. Thanks for all your other comments, although now that you said that the comparison operator can't be overloaded, I'm going to try and do just that. :P
Pessimist
@Pessimist: The answer above is extended with an example using the method described by RBerteig
Doug Currie
@Doug Currie: thank you for that. I've chosen your answer. That was extremely helpful. :)
Pessimist
The thing is, because Lua doesn't support hard references and is dynamic typed, some operator overloads flat out don't make sense for Lua, like assignment. If you do a comparison, first Lua will compare the types, and only continue if they are the same. Else, false. This means that you cannot overload a table to be equal to a string.
DeadMG
@DeadMG: This way you may have secure sandbox with setmetatable() available to user
Alexander Gladysh
If you can get a security risk by changing a string metatable, your code has MUCH bigger problems.
DeadMG
@DeadMG: You *will* get a security risk if you allow untrusted code to change metatables for non-table types.
Alexander Gladysh
How, precisely? If you don't expose unsafe functions, the user cannot set an unsafe function to the metatable. If you do expose unsafe functions... the guy can just execute them anyway. How, specifically, can a non-table metatable result in a security risk, as opposed to any other Lua code?
DeadMG
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.
Alexander Gladysh
+2  A: 

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.

Alexander Gladysh
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.
RBerteig
Thanks for the links. Please see EDIT 1 above.
Pessimist
That is only true for comparison operators. It isn't true for generic operators. Your posted link is six years out of date.
DeadMG
@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.
Alexander Gladysh
That I didn't know, and I was reading the PiL. Thank you.
Pessimist
@Pessimist: Please consider buying second edition then: http://www.inf.puc-rio.br/~roberto/pil2/
Alexander Gladysh