Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix various issues and cleanup whitespace #9

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 57 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ you find any mistakes or typos.

print(foo[0], bar[0]) -- => 9 9
print(foo[1], bar[1]) -- => 3 3
print(foo[2], bar[2]) -- => 2 2
print(foo[2], bar[2]) -- => 2 2
```

**[[⬆]](#TOC)**
Expand All @@ -95,7 +95,7 @@ you find any mistakes or typos.
```lua
-- bad
local player = {
attack = function()
attack = function()
-- ...stuff...
end
}
Expand All @@ -109,35 +109,60 @@ you find any mistakes or typos.
}
```

- Consider `nil` properties when selecting lengths.
A good idea is to store an `n` property on lists that contain the length
- The length operator does not work as you may expect on tables that
contain `nil`.
A good idea is to store an `n` property on lists that contain their length
(as noted in [Storing Nils in Tables](http://lua-users.org/wiki/StoringNilsInTables))

```lua
-- nils don't count
local list = {}
list[0] = nil
list[1] = "item"
list[2] = nil

print(#list) -- 0
print(select('#', list)) -- 1
print(#list) -- 1
```

```lua
local list = {}
list[1] = "item"
list[2] = nil
list[3] = "item"

print(#list) -- undefined result
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should say that it returns 1 rather than the expected 3.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With a given Lua implementation. But the definition in the language is even worse. In Lua 5.1:

any integer index n such that t[n] is not nil and t[n+1] is nil

So it could be 1 or 3.

In Lua 5.2 it is even clearer:

Unless a __len metamethod is given, the length of a table t is only defined if the table is a sequence, that is, the set of its positive numeric keys is equal to {1..n} for some integer n

So the operator could return anything. Or crash your program, for that matter. Actually I expect some later Lua implementations to raise an error in that situation.

Anyway, my point is: you cannot rely on it being 3 but you cannot rely on it being 1 either.

EDIT: If you think this undefined stuff is theoretical, guess what this prints:

print(#{1, 2, nil, 3})

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true; maybe expand it as result depends on Lua implementation, then?

I admit, I only tested it in Lua 5.1.5 and Luajit 2.0.2 to confirm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it depends on the implementation. And it is not consistent even on Lua 5.1.5. As I said in my edit above, if you put the hole just one step further it doesn't give the same answer:

Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> list = {}
> list[1] = "item"
> list[2] = "item"
> list[3] = nil
> list[4] = "item"
> =#list
4

If you are interested in the "why" see the implementation. Hint: binary search.

```

- The length operator always counts from 1. If you store values at negative
positions in a table (including 0) they will be ignored.

```lua
local list = {}
list[0] = "item"
list[1] = "item"

print(#list) -- 1
```

- When tables have functions, use `self` when referring to itself.

```lua
-- bad
local fullname = function(this)
return this.first_name + " " + this.last_name
end
local me = {
fullname = function(this)
return this.first_name + " " + this.last_name
end
fullname = fullname,
first_name = "Jack",
last_name = "Smith",
}

-- good
local fullname = function(self)
return self.first_name + " " + self.last_name
end
local me = {
fullname = function(self)
return self.first_name + " " + self.last_name
end
fullname = fullname,
first_name = "Jack",
last_name = "Smith",
}
```

Expand All @@ -161,7 +186,7 @@ you find any mistakes or typos.
local fullName = 'Bob ' .. self.lastName
```

- Strings longer than 80 characters should be written across multiple lines
- Strings longer than 80 characters should be written across multiple lines
using concatenation. This allows you to indent nicely.

```lua
Expand Down Expand Up @@ -219,7 +244,7 @@ you find any mistakes or typos.

```lua
-- bad
local function nope(name, options, arg)
local function nope(name, options, arg)
-- ...stuff...
end

Expand Down Expand Up @@ -281,7 +306,7 @@ you find any mistakes or typos.
age = 28
}

local function getProp(prop)
local function getProp(prop)
return luke[prop]
end

Expand Down Expand Up @@ -371,7 +396,7 @@ you find any mistakes or typos.
end
```

- Prefer *true* statements over *false* statements where it makes sense.
- Prefer *true* statements over *false* statements where it makes sense.
Prioritize truthy conditions when writing multiple conditions.

```lua
Expand Down Expand Up @@ -458,8 +483,8 @@ you find any mistakes or typos.
if test < 1 and do_complicated_function(test) == false or
seven == 8 and nine == 10 then

do_other_complicated_function()
return false
do_other_complicated_function()
return false
end
```

Expand All @@ -472,17 +497,17 @@ you find any mistakes or typos.

```lua
-- bad
function()
function()
∙∙∙∙local name
end

-- bad
function()
function()
∙local name
end

-- good
function()
function()
∙∙local name
end
```
Expand Down Expand Up @@ -513,14 +538,14 @@ you find any mistakes or typos.

```lua
-- bad
(function(global)
(function(global)
-- ...stuff...
end)(self)
```

```lua
-- good
(function(global)
(function(global)
-- ...stuff...
end)(self)

Expand All @@ -547,11 +572,11 @@ you find any mistakes or typos.
```lua
--bad
local thing = {1,2,3}
thing = {1 , 2 , 3}
thing = {1 ,2 ,3}
thing = { 1 , 2 , 3 }
thing = { 1 ,2 ,3 }

--good
local thing = {1, 2, 3}
local thing = { 1, 2, 3 }
```

- Add a line break after multiline blocks.
Expand Down Expand Up @@ -666,12 +691,12 @@ you find any mistakes or typos.

```lua
-- bad
local function q()
local function q()
-- ...stuff...
end

-- good
local function query()
local function query()
-- ..stuff..
end
```
Expand Down Expand Up @@ -763,7 +788,7 @@ you find any mistakes or typos.
## <a name='file-structrure'>File Structure</a>

- Files should be named in all lowercase.
- Lua files should be in a top-level `src` folder. The main library file should
- Lua files should be in a top-level `src` folder. The main library file should
be called `modulename.lua`.
- Rockspecs, license, readme, etc should be in the top level.
- Tests should be in a top-level spec folder.
Expand All @@ -789,7 +814,7 @@ you find any mistakes or typos.

## <a name='testing'>Testing</a>

- Use [busted](olivinelabs.com/busted) and write lots of tests in a /spec
- Use [busted](olivinelabs.com/busted) and write lots of tests in a /spec
folder. Separate tests by module.
- Use descriptive `describe` and `it` blocks so it's obvious to see what
precisely is failing.
Expand Down