Académique Documents
Professionnel Documents
Culture Documents
Lua Gotchas
Lua Gotchas
1 Calling methods 2 Values which are false 3 Undeclared variables 3.1 .. are global by default 3.2 Variables must be declared before use. 4 All numbers are floating point 5 When does automatic conversion to string occur? 6 Tables are both arrays and dictionaries 6.1 Arrays start at one 6.2 Table keys 6.3 Undefined field access is a feature 6.4 Arrays with holes are bad news 6.5 Element order with pairs() is arbitrary 7 When to use parentheses with functions? 8 Expressions with multiple values 8.1 Functions can return multiple values 8.2 A Superficial similarity with Python 8.3 Multiple Assignments in Declarations 9 Values and references 10 Using metatables 10.1 __index is a fallback 10.2 __index can be a table 10.3 __eq cannot be used to compare arbitrary values 'Gotchas' are Lua features which are often confusing at first, if you are used to other languages. Here is a short list compiled from the Lua mailing list, particularly by Timothy Hunter.
1 Calling methods
If you are used to other languages, then o b j . m e t h o d ( )looks like a method call, but really it is just looking up 'method' in the context of o b jand then calling that function. To make a proper method call, use o b j : m e t h o d ( )which is 'syntactical sugar' for o b j . m e t h o d ( o b j )- that is, the colon passes the object as the first argument as s e l f . Common methods encountered in basic Lua programming are the string methods, like s : f i n d ( " h e l l o " )being short for s t r i n g . f i n d ( s , " h e l l o " ) .
3 Undeclared variables
www.luafaq.org/gotchas.html#T7 1/7
5/1/13
Lua Gotchas
but the equivalent Lua does not because z o ghas not yet been declared:
f u n c t i o nf o o ( ) l o c a lf u n c t i o nb a r ( )z o g ( )e n d l o c a lf u n c t i o nz o g ( )p r i n t" Z o g ! "e n d b a r ( ) e n d
in Lua, but 1 0 = = " 1 0 "is not true. In an arithmetic expression, Lua will attempt to convert strings to numbers, otherwise you will get a 'attempt to perform arithmetic on a string value'. Fortunately, string concatenation is a separate operator, so JavaScript-style weirdness does not happen so often: " 1 0 " . . " 2 0 "is unambiguously "1020".
5/1/13
Lua Gotchas
Lua tables are the ultimate one-stop-shop of data structures. It can be confusing that a table can behave like both kinds of containers at once, such as { 1 , 2 , 3 , e n a b l e = t r u e } . So you will see reference to the array-part and the 'hash' part of a table.
5/1/13
Lua Gotchas
Lua is different in that strings require parentheses if you want to call string methods, such as ( ' % s = % d ' ) : f o r m a t ( ' h e l l o ' , 4 2 ) . But there are important cases when you can leave out parentheses, such as p r i n t' h e l l o 'and m y f u n c{ 1 , 2 , 3 ;e n a b l e = t r u e } . If the single argument of a function is a string or a table constructor, then they can be safely left out. (The old-style Python p r i n t' h e l l o 'has another meaning, since p r i n tis a statement.)
A powerful and unusual feature, but there are several things to be aware of.
(Note that the parentheses in the string pattern have special meaning, like in standard regular expressions.) It is easy to write a function that returns multiple values:
f u n c t i o ns u m p r o d ( x , y )r e t u r nx + y ,x * ye n d
(The comma is never an operator in Lua; it is only a delimiter.) Furthermore, these multiple return values are treated specially in function calls and table constructors. The expression { s u m p r o d ( 1 0 , 2 0 ) }is the table { 3 0 , 2 0 0 }and p r i n t ( s u m p r o d ( 1 0 , 2 0 ) )has the same effect as p r i n t ( 3 0 , 2 0 0 ) . The function u n p a c kgoes the other way:
>p r i n t ( u n p a c k { 1 , 2 , 3 } ) 1 2 3
This is a powerful and efficient feature but it can bite you. For instance, consider this function that turns a string into hexadecimal bytes:
f u n c t i o ne s c a p e ( s ) r e t u r ns : g s u b ( ' . ' , f u n c t i o n ( s )r e t u r n( ' % 2 X ' ) : f o r m a t ( s : b y t e ( 1 ) )e n d ) e n d
5/1/13
Lua Gotchas
2 0
s t r i n g . g s u breturns the result of the substitution plus the number of substitutions made -
so this function can mess up code that is expecting exactly one return code. The best solution is to enclose the expression in parentheses:
f u n c t i o ne s c a p e ( s ) r e t u r n( s : g s u b ( ' . ' , f u n c t i o n ( s )r e t u r n( ' % 2 X ' ) : f o r m a t ( s : b y t e ( 1 ) )e n d ) ) e n d
(Or you could assign the result of g s u bto a local variable and return that.) The rule for expanding multiple results only works for the last argument, so be careful with expressions like { f ( ) , g ( ) }- if f ( )returned multiple values, then only the first one would be used. (There has been a proposal for an operator that would 'unpack' multiple values in any position.)
In Lua, the function f u nreturns two values, in Python it returns one t u p l evalue, which it then helpfully unpacks in this context. This is one of the many little things that makes Lua the 'speed queen' of dynamic languages, since there is no extra hidden overhead with this assignment. A Python programmer may expect this to also implicitly unpack a table:
x , y={ 1 , 2 }
But there is no such magic in Lua, and you must explicitly use u n p a c k . It's a gotcha because it is not an error; xbecomes the table value, and ybecomes n i l .
and you will get an 'unexpected symbol near '='' error if you try the first syntax.
www.luafaq.org/gotchas.html#T7
5/7
5/1/13
Lua Gotchas
values; tables are never compared 'element by element'. It is straightforward to do this in Lua; for example see how d e e p c o m p a r eis defined in Penlight In the same way t 1=t 2does not make a copy of t 2 . The variable t 1will become another reference to the value of t 2 . Assigning to t 1 [ 1 ]will change t 2 [ 1 ] , because they simply point to the same object. Now, how does string equality work? Unlike Java, s 1 = = s 2will work on equal strings, character by character. This is because there is only ever one instance of any particular string stored in memory, so comparison is very quick (this is called interning), for an extra cost of string creation. This can work because strings are 'immutable', there is no way in Lua to modify the contents of a string directly. The same lessons taught to Java programmers apply here: building up a large string by concatenation creates a lot of temporary strings that can stress the garbage collector. The Lua way is to put the strings into a table and then use t a b l e . c o n c a t . If you are a C programmer, this may seem massively inefficient, but the answer is that Lua strings are not the right data structure for modification. Representing a string as a table of string fragments (sometimes called a 'rope') is much more efficient.
10 Using metatables
Lua has powerful meta-programming abilities through mechanism of metatables . Different table values can be given common behaviour by giving them the same metatable, and so you can think of it as a generalisation of the 'class' concept in other dynamic languages.
Cute, and incredibly powerful. In Lua 4.0 the equivalent concept was called a 'fallback' and that word describes the behaviour very well. A common misunderstanding is that _ _ i n d e xoverrides all table accesses, but this is not so. In a similar way, _ _ n e w i n d e xonly kicks in if the key does not exist in the table. (If you do need to do something for each table key access, then proxy tables are the suggested solution. This technique involves deliberately keeping the table empty, and keeping the implementation data separate. Then _ _ i n d e xwill always fire and you can return whatever you like - this can be used to implement true properties with getters and setters.)
5/1/13
Lua Gotchas
To construct a new instance of C , you make a new table and set its metatable to C .
f u n c t i o nC . n e w ( v a l u e ) l o c a lo b j=s e t m e t a t a b l e ( { } , C ) o b j . v a l u e=v a l u e r e t u r no b j e n d
The key to this trick is C . _ _ i n d e x=C ; people often think that merely putting functions in the metatable will allow objects to access them, but all unknown field accesses have to go through _ _ i n d e x , and this assignment lets objects find their functions in the metatable.
www.luafaq.org/gotchas.html#T7
7/7