[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Does PIL (3rd edition) repeatedly misuse the length operator on tables and invoke undefined behavior?
- From: polyglot@...
- Date: Wed, 17 Sep 2014 23:50:59 +1000
5.2 REFERENCE MANUAL
"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. In that case, n is its length."
*** Conclusion ***: Without a __len metamethod, an empty table has
undefined
length.
5.1 REFERENCE MANUAL
"The length of a table t is defined to be any integer index n such that
t[n]
is not nil and t[n+1] is nil; moreover, if t[1] is nil, n can be zero.
For a
regular array, with non-nil values from 1 to a given n, its length is
exactly that n, the index of its last value. If the array has "holes"
(that
is, nil values between other non-nil values), then #t can be any of the
indices that directly precedes a nil value (that is, it may consider any
such nil value as the end of the array)."
*** Conclusion ***: An empty table (t[1] is nil) may or may not have a
length of zero.
===========================================================================
So I'm assuming the following idiomatic code invokes undefined behavior:
a = {}
a[#a + 1] = 'foo'
As does this code (because of the implicit #a+1):
a = {}
table.insert(a, 'foo')
===========================================================================
Yet such code appears repeatedly in PIL (3rd edition), and I haven't
seen any errata for it:
PAGE 94
threads = {} -- list of all live threads
-- [...]
table.insert(threads, co)
PAGE 95
local timedout = {}
-- [...]
timedout[#timedout + 1] = res
PAGE 99 and PAGE 100
local words = {}
for w in pairs(counter) do
words[#words + 1] = w
end
PAGE 113 and PAGE 114
local t = {}
for line in io.lines() do
t[#t + 1] = -- [...]
end
PAGE 115
path = path or {}
visited = visited or {}
if visited[curr] then -- node already visited?
return nil -- no path here
end
visited[curr] = true -- mark node as visited
path[#path + 1] = curr -- add it to path
PAGE 129
function Set.tostring (set)
local l = {} -- list to put all elements from the set
for e in pairs(set) do
l[#l + 1] = e
end
PAGE 195
t = {}
for line in io.lines() do
table.insert(t, line)
end
PAGE 196
a = {}
for n in pairs(lines) do a[#a + 1] = n end
PAGE 197
local a = {}
for n in pairs(t) do a[#a + 1] = n end
PAGE 202
local t = {} -- table to store the indices
local i = 0
while true do
i = string.find(s, "\n", i+1) -- find next newline
if i == nil then break end
t[#t + 1] = i
end
PAGE 203
words = {}
for w in string.gmatch(s, "%a+") do
words[#words + 1] = w
end
PAGE 212
function encode (t)
local b = {}
for k,v in pairs(t) do
b[#b + 1] = (escape(k) .. "=" .. escape(v))
end
PAGE 218
local a = {}
a[#a + 1] = -- [...]
PAGE 223
local lines = {}
-- read the lines in table 'lines'
for line in io.lines() do lines[#lines + 1] = line end