Documenting Lua gotchas for newbies.

classic Classic list List threaded Threaded
68 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

Documenting Lua gotchas for newbies.

Pierre-Yves Gérardy
Following the floating point discussion, I tried to look for a compilation of the various gotchas Lua beginners encounter, but I couldn't find one, so I decided to compile one...

Right now, I can think of two of them:

- Floating point inaccuracies. A simplified version of Patrick Rapin's "math.compare (x,y,delta)" [1] could be proposed as a workaround.
- The fact that you have to declare locals before using them.


Are there other potential traps? On what did you stumble while learning the language?

Kind regards,
-- Pierre-Yves

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Pierre-Yves Gérardy
Clarification:

- Floating point inaccuracies. A simplified version of Patrick Rapin's "math.compare (x,y,delta)" [1] could be proposed as a workaround.

I mean: "provide it as a code sample on the noob FAQ page", not "add it to the standard lib".
Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Timothy Hunter
In reply to this post by Pierre-Yves Gérardy
I wrote a Lua programming handout for my job for use by the long-time C programmers in our department. In it there is a section called "Footguns" where I listed these 5 gotchas. 

  1. The "key" in t.key is the constant string "key", not a variable named "key".
  2. A table that contains at least one nil is a hash, not an array. This means that #t may not return the number of elements in the table.
  3. Be careful to distinguish between a period and a colon when calling functions. t.f() is not the same thing as t:f().
  4. Lua arrays start at 1, not 0.
  5. Only false and nil are false. 0 is true.
  6. Undeclared variables are global.


On Dec 1, 2010, at Dec 1 3:28 PM, Pierre-Yves Gérardy wrote:

Following the floating point discussion, I tried to look for a compilation of the various gotchas Lua beginners encounter, but I couldn't find one, so I decided to compile one...

Right now, I can think of two of them:

- Floating point inaccuracies. A simplified version of Patrick Rapin's "math.compare (x,y,delta)" [1] could be proposed as a workaround.
- The fact that you have to declare locals before using them.


Are there other potential traps? On what did you stumble while learning the language?

Kind regards,
-- Pierre-Yves


Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Lorenzo Donati-2
In reply to this post by Pierre-Yves Gérardy
Pierre-Yves Gérardy wrote:
> Following the floating point discussion, I tried to look for a
> compilation of the various gotchas Lua beginners encounter, but I
> couldn't find one, so I decided to compile one...
>

Very commendable initiative! :-)

If these could be considered gotchas:

1. I discovered "late in the game" that the most efficient way to append
an item to an array was
a[#a+1]=item
and not
table.insert(a,item)


2. (this is more on the "someone tell me the rationale" side)
I was really puzzled that no library copy operation existed (ie.
table.copy).
After all the only data structure in Lua are tables, and making shallow
or deep copies of them is not something one should consider an
infrequent operation. Only after a while I began to understand the
minimalistic "philosophy" of Lua.






Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Sam Roberts
In reply to this post by Pierre-Yves Gérardy
2010/12/1 Pierre-Yves Gérardy <[hidden email]>:
> Following the floating point discussion, I tried to look for a compilation
> of the various gotchas Lua beginners encounter, but I couldn't find one, so
> I decided to compile one...
> Right now, I can think of two of them:
> - Floating point inaccuracies.

Floating point behaviour is common to most programming languages, what
does this have to do with lua?

ruby:

irb(main):010:0> x = 1.1; x = x + 0.1; print("%.20f\n" % x); print(x == 1.2)
1.20000000000000017764
false=> nil

python:

>>> x = 1.1; x = x + 0.1; print("%.20f\n", x); print(x == 1.2)
('%.20f\n', 1.2000000000000002)
False

>  x = 1.1; x = x + 0.1; print(string.format("%.20f", x)); print(x == 1.2)
1.20000000000000017764
false

Never use "==" to compare float/double values is even in some C coding
standards and compiler warnings.

Cheers,
Sam

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Peter Odding-3
In reply to this post by Pierre-Yves Gérardy
> Following the floating point discussion, I tried to look for a
> compilation of the various gotchas Lua beginners encounter, but I
> couldn't find one, so I decided to compile one...
>
> ...
>
> Are there other potential traps? On what did you stumble while learning
> the language?

I just stumbled onto something in the C API that doesn't seem to be
documented in the reference manual and caused a bug in my Lua/APR
binding (reported a few hours ago on GitHub*):

When you create a new userdata by calling lua_newuserdata() the newly
created userdata gets a default environment table installed which turns
out to be ... wait for it ... the global `package' table :-|. I don't
consider this useful behaviour and I couldn't find any mention of it in
the Lua 5.1 reference manual (please correct me if I'm wrong).

 From the lua-users wiki** I understand that in the current
implementation the environment table must point to somewhere, this might
explain the nonsensical default.

  - Peter

* https://github.com/xolox/lua-apr/issues/#issue/1
** http://lua-users.org/wiki/UserDataRefinement

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Pierre-Yves Gérardy
In reply to this post by Sam Roberts

-- Pierre-Yves


On Wed, Dec 1, 2010 at 21:54, Sam Roberts <[hidden email]> wrote:
2010/12/1 Pierre-Yves Gérardy <[hidden email]>:
 
Floating point behaviour is common to most programming languages, what
does this have to do with lua?

That's true. However, the question is asked often on the list, which warrants a FAQ entry, by definition. 

I joind the list in February of this year, and I've found 4 occurrences of newbie questions related to floating point arithmetics.

"Floating Point inaccuracies"

"math.floor and rounding"

"Why do some math functions return -0"

"not all numbers are treated the same way"

Cheers,
--Pierre-Yves
Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Axel Kittenberger
In reply to this post by Lorenzo Donati-2
> a[#a+1]=item
> and not
> table.insert(a,item)

Way! I didn't know that, I use table.insert(a, item) everwhere, how
much is the difference?

> 2. (this is more on the "someone tell me the rationale" side)
> I was really puzzled that no library copy operation existed (ie.
> table.copy).
> After all the only data structure in Lua are tables, and making shallow or
> deep copies of them is not something one should consider an infrequent
> operation. Only after a while I began to understand the minimalistic
> "philosophy" of Lua.

Not in favor of deep copy, but I suppose a C implementation that
copies the whole hashtable should way effectiver than
for k, v in pairs(table) do
   newtable[k] = v
end
shouldn't it?

And I do this occassionaly, but maybe you just proven me, that I'm not
actually using the effectivst things?

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

David Manura
In reply to this post by Pierre-Yves Gérardy
2010/12/1 Pierre-Yves Gérardy <[hidden email]>:
> Following the floating point discussion, I tried to look for a compilation
> of the various gotchas Lua beginners encounter, but I couldn't find one, so
> I decided to compile one...

This might be an after-the-gotcha rather than a gotcha, but one thing
I've noticed is people asking for interpretations of traceback error
messages like "foo.lua:10: ... 'x' (a nil value) foo.lua:10 in
function 'f'  bar.lua:20 in function 'g'", which means that on line 10
of file "foo.lua" in function f, the variable x is undefined, and f
was called by function f on line 20 of bar.lua.  It makes me wonder
whether something along the lines of [1] is warranted.

[1] http://github.com/ignacio/StackTracePlus

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Jim Whitehead II
In reply to this post by Lorenzo Donati-2
On Wed, Dec 1, 2010 at 8:53 PM, Lorenzo Donati
<[hidden email]> wrote:

> Pierre-Yves Gérardy wrote:
>>
>> Following the floating point discussion, I tried to look for a compilation
>> of the various gotchas Lua beginners encounter, but I couldn't find one, so
>> I decided to compile one...
>>
>
> Very commendable initiative! :-)
>
> If these could be considered gotchas:
>
> 1. I discovered "late in the game" that the most efficient way to append an
> item to an array was
> a[#a+1]=item
> and not
> table.insert(a,item)

Strictly speaking, isn't the fastest method:

local tbl = {}
local c = 0
c = c + 1
tbl[c] = item

It's a micro benchmark, but I believe this was the winner.

- Jim

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Axel Kittenberger
In reply to this post by Pierre-Yves Gérardy
Back when I started with Lua ipairs() and pairs() where quite a gotcha
for me. ipairs() not retrieving all elements if there is one missing,
and pairs() not returning stuff "in order". Getting to the mechanics a
little its all very understandable why it is the way it is. As newbie
it can be a bit confusing/surprising tough.  At the start I always
used pairs() as most the time it did came up in the order I expected,
until there came that huh?moment.

Another surprise was when starting to take us of metatables that
__newindex and __index are only called if the value isnt there.
Altough it would have helped to read the docs better.

2010/12/1 Pierre-Yves Gérardy <[hidden email]>:

> Following the floating point discussion, I tried to look for a compilation
> of the various gotchas Lua beginners encounter, but I couldn't find one, so
> I decided to compile one...
> Right now, I can think of two of them:
> - Floating point inaccuracies. A simplified version of Patrick Rapin's
> "math.compare (x,y,delta)" [1] could be proposed as a workaround.
> - The fact that you have to declare locals before using them.
>
> Are there other potential traps? On what did you stumble while learning the
> language?
> Kind regards,
> -- Pierre-Yves
>
> 1. http://article.gmane.org/gmane.comp.lang.lua.general/71397

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Michal Kottman
In reply to this post by Lorenzo Donati-2
On Wed, 2010-12-01 at 21:53 +0100, Lorenzo Donati wrote:

> Pierre-Yves Gérardy wrote:
> > Following the floating point discussion, I tried to look for a
> > compilation of the various gotchas Lua beginners encounter, but I
> > couldn't find one, so I decided to compile one...
> >
>
> Very commendable initiative! :-)
>
> If these could be considered gotchas:
>
> 1. I discovered "late in the game" that the most efficient way to append
> an item to an array was
> a[#a+1]=item
> and not
> table.insert(a,item)
>
>
> 2. (this is more on the "someone tell me the rationale" side)
> I was really puzzled that no library copy operation existed (ie.
> table.copy).
> After all the only data structure in Lua are tables, and making shallow
> or deep copies of them is not something one should consider an
> infrequent operation. Only after a while I began to understand the
> minimalistic "philosophy" of Lua.
>

Maybe http://snippets.luacode.org/ (work in progress) could serve as a
good starting point for beginners...


Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Timothy Hunter
In reply to this post by Pierre-Yves Gérardy
I wrote a Lua programming handout for my job for use by the long-time C programmers in our department. In it there is a section called "Footguns" where I listed these 5 gotchas. 

  1. The "key" in t.key is the constant string "key", not a variable named "key".
  2. A table that contains at least one nil is a hash, not an array. This means that #t may not return the number of elements in the table.
  3. Be careful to distinguish between a period and a colon when calling functions. t.f() is not the same thing as t:f().
  4. Lua arrays start at 1, not 0.
  5. Only false and nil are false. 0 is true.
  6. Undeclared variables are global.

On Dec 1, 2010, at Dec 1 3:28 PM, Pierre-Yves Gérardy wrote:

Following the floating point discussion, I tried to look for a compilation of the various gotchas Lua beginners encounter, but I couldn't find one, so I decided to compile one...

Right now, I can think of two of them:

- Floating point inaccuracies. A simplified version of Patrick Rapin's "math.compare (x,y,delta)" [1] could be proposed as a workaround.
- The fact that you have to declare locals before using them.


Are there other potential traps? On what did you stumble while learning the language?

Kind regards,
-- Pierre-Yves


Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Miles Bader-2
In reply to this post by Pierre-Yves Gérardy
Pierre-Yves Gérardy <[hidden email]> writes:
> Following the floating point discussion, I tried to look for a compilation
> of the various gotchas Lua beginners encounter, but I couldn't find one, so
> I decided to compile one...
>
> Right now, I can think of two of them:
>
> - Floating point inaccuracies. A simplified version of Patrick Rapin's
> "math.compare (x,y,delta)" [1] could be proposed as a workaround.

This isn't a "Lua gotcha" though -- it's an issue with pretty much any
programming languages that doesn't use decimal arithmetic (that is to
say, it's an issue with almost all of them)...

> - The fact that you have to declare locals before using them.

Er, sure...

I'm a bit confused as to how somebody can be tripped up by this though
-- if they have the concept of a "local variable" at all, then surely
they're acquainted with the notion of declaring them, as that's the
only way to make a local variable in 99% of programming languages
(ignoring function parameters, but presumably they're "special")...

(if they're _not_ familiar with the concept of local variables, then
their programs may suck, but Lua's behavior will presumably seem
natural, as they'll think all variables are global...)

-Miles

--
`The suburb is an obsolete and contradictory form of human settlement'

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Javier Guerra Giraldez
2010/12/1 Miles Bader <[hidden email]>:
> as that's the
> only way to make a local variable in 99% of programming languages

many languages (especially beginner-friendly languages) assume local by default

--
Javier

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Pierre-Yves Gérardy
In reply to this post by Miles Bader-2
2010/12/2 Miles Bader <[hidden email]>
> - The fact that you have to declare locals before using them.

Er, sure...

I'm a bit confused as to how somebody can be tripped up by this though
-- if they have the concept of a "local variable" at all, then surely
they're acquainted with the notion of declaring them, as that's the
only way to make a local variable in 99% of programming languages
(ignoring function parameters, but presumably they're "special")...

In Javascript, function declarations are hoisted, for example. IIRC, in Ruby, you can define the methods of a class in any order you like, and I think that the same goes for attributes. In Ruby and Python, variables are local by default, and I don't think that the order in which they are defined matters.

I remember trying this, expecting it to work:

    local function foo() return bar() end
    local function bar() end

    assert(foo()) --> false

a variation of this is this other noob error (I did it too):

    local tbl = {
        foo = function(arg) tbl.field = arg end
    }

In Python the following works:

    def foo():
        def bar ():
            zog()
        def zog():
            print "Zog!"
        bar()

    foo() # prints "Zog!"
    bar() # error ( bar is a local inside foo()).



-- Pierre-Yves
 
Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Lorenzo Donati-2
In reply to this post by Jim Whitehead II
Jim Whitehead II wrote:
> On Wed, Dec 1, 2010 at 8:53 PM, Lorenzo Donati
> <[hidden email]> wrote:
[snip]

>> 1. I discovered "late in the game" that the most efficient way to append an
>> item to an array was
>> a[#a+1]=item
>> and not
>> table.insert(a,item)
>
> Strictly speaking, isn't the fastest method:
>
> local tbl = {}
> local c = 0
> c = c + 1
> tbl[c] = item
>
> It's a micro benchmark, but I believe this was the winner.
>
> - Jim
>
>
>

Ouch! Yes. I implicitly assumed in my example that "a" was local.
But that
local c = 0
is a typo? Shouldn't it be
local c = #tbl
?

Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Lorenzo Donati-2
In reply to this post by Pierre-Yves Gérardy
Pierre-Yves Gérardy wrote:

> Following the floating point discussion, I tried to look for a
> compilation of the various gotchas Lua beginners encounter, but I
> couldn't find one, so I decided to compile one...
>
> Right now, I can think of two of them:
>
> - Floating point inaccuracies. A simplified version of Patrick Rapin's
> "math.compare (x,y,delta)" [1] could be proposed as a workaround.
> - The fact that you have to declare locals before using them.
>
>
> Are there other potential traps? On what did you stumble while learning
> the language?
>
> Kind regards,
> -- Pierre-Yves
>
> 1. http://article.gmane.org/gmane.comp.lang.lua.general/71397

Please forgive me if I give the impression to push people, it's not my
intent, but IMHO it could be worth consider a form of coordination
(merging?) of different FAQs, like that excellent unofficial FAQ by
Steve Donovan:

http://batbytes.com/luafaq

Best Regards,

--
Lorenzo


Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Pierre-Yves Gérardy
On Thu, Dec 2, 2010 at 07:15, Lorenzo Donati <[hidden email]> wrote:
Please forgive me if I give the impression to push people, it's not my intent, but IMHO it could be worth consider a form of coordination (merging?) of different FAQs, like that excellent unofficial FAQ by Steve Donovan:
http://batbytes.com/luafaq

Definitely. I intended to create a page on the Wiki, but I'm open to suggestions.
Why hasn't Steve's FAQ been merged into the Wiki?

-- Pierre-Yves


 
Reply | Threaded
Open this post in threaded view
|

Re: Documenting Lua gotchas for newbies.

Jonathan Castello-2
In reply to this post by Lorenzo Donati-2
Nope. tbl was defined just before it, as an empty table. #tbl would be
0 anyways.

On Wed, Dec 1, 2010 at 9:48 PM, Lorenzo Donati
<[hidden email]> wrote:
> Ouch! Yes. I implicitly assumed in my example that "a" was local.
> But that
> local c = 0
> is a typo? Shouldn't it be
> local c = #tbl
> ?

1234