[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: [ANN] Penlight Libraries, First release
- From: Flemming Madsen <lua@...>
- Date: Sun, 10 May 2009 21:36:04 +0200
Great piece of work! Just the batteries needed for our platform.
A couple of thoughts around the List library.
1) Why not return the list from all calls that would not otherwise
return anything?
This would let one write eg. L:clear:extend({3,2,1}):sort() as
noted elsewhere
2) Include all table operations. One should be able to write L:concat('\t'), not
table.concat(L, '\t')
3) Related to the above, methods *really* should have the same meaning as the
table operation of the same name. L:remove(2) should not be
something completely
different from table.remove(L, 2)! I appreciate the python
heritage, but this is Lua
after all :-)
I have included a patch that implements the above. A 'return self' is
thrown in at numerous places. Remove is renamed to purge, and remove
is now an alias for pop. Delete is like remove but returns the list
removed from.
Also there is a fix in pretty.write so it wont throw away numerix
indexes > #t :)
/Flemming
On Wed, Apr 29, 2009 at 4:04 PM, steve donovan
<steve.j.donovan@gmail.com> wrote:
>
> Hi guys,
>
> A number of substantial changes since the last beta.
>
> The map and reduce functions now take the function first, as Nature intended.
>
> The Python-like overloading of '*' for strings has been dropped, since it
> is silly. Also, strings are no longer callable; use 's:at(1)' instead of
> 's(1)' - this tended to cause Obscure Error messages.
>
> Wherever a function argument is expected, you can use the operator strings
> like '+','==',etc as well as pl.operator.add, pl.operator.eq, etc.
> (see end of pl/operator.lua for the full list.) So you can say:
>
> reduce('+',tbl)
>
> tablex now has compare() and compare_no_order(). An explicit set()
> function has been added which constructs a table with the specified
> keys, all set to a value of true.
>
> List has reduce() and partition() (This is a cool function which
> separates out elements of a list depending on a classifier function.)
>
> There is a new array module which generalizes tablex operations like
> map and reduce for two-dimensional arrays. An iterator is provided
> that behaves like a generalized ipairs:
>
> for i,j,v in array.iter(A,true) do print(i,j,v) end
>
> (It complements but does not aim to provide matrix operations)
>
> The famous iterator over permutations from PiL 9.3 has been included;
> I needed it for array.product, which does a cartesian product of two lists.
>
> David's list comprehension library has been included.
>
> Also, utils now contains his memoize function, plus a useful function
> args which captures the case where varargs contains nils.
>
> There was a bug with dir.copyfile where the flag was the wrong way round.
>
> config.lines() had a problem with continued lines.
>
> Some operators were missing in pl.operator; have renamed them to be
> consistent with the Lua metamethod names.
>
> There is no doubt a fair amount of redundant and tautologous functionality,
> but the winners will improve and the losers will be weeded out.
> No cows are sacred at this stage; please try to break.
>
> Any suggestions are welcome.
>
> http://penlight.luaforge.net/penlight.html
>
> http://luaforge.net/frs/download.php/4051/pl.0.6.3.zip
>
> steve d.
--- penlight/lua/pl/pretty.lua.orig
+++ penlight/lua/pl/pretty.lua
@@ -46,9 +46,15 @@
elseif tp == 'table' then
local newindent = indent..space
putln('{')
+ local max = 0
+ for i,val in ipairs(t) do
+ put(indent)
+ writeit(val,indent,newindent)
+ max = i
+ end
for key,val in pairs(t) do
local numkey = type(key) == 'number'
- if not numkey or key < 1 then -- non-array indices
+ if not numkey or key < 1 or key > max then -- non-array indices
if numkey or not is_identifier(key) then
if not numkey then key = '"'..key..'"' end
key = '['..key..']'
@@ -57,10 +63,6 @@
writeit(val,indent,newindent)
end
end
- for _,val in ipairs(t) do
- put(indent)
- writeit(val,indent,newindent)
- end
eat_last_comma()
putln(oldindent..'},')
else
--- penlight/lua/pl/list.lua.orig
+++ penlight/lua/pl/list.lua
@@ -23,7 +23,7 @@
List = {}
List.__index = List
-- we give the metatable its own metatable so that we can call it like a function!
-_ListMT = {}
+local _ListMT = {}
setmetatable(List,_ListMT)
function _ListMT.__call(tbl,arg)
@@ -93,46 +93,59 @@
---Add an item to the end of the list.
-- @param i An item
+-- @return the List
function List:append(i)
tinsert(self,i)
+ return self
end
--- Extend the list by appending all the items in the given list.
-- equivalent to 'a[len(a):] = L'.
-- @param L Another List
+-- @return the List
function List:extend(L)
assert(type(L)=="table","List:extend expecting a table")
for i,v in ipairs(L) do tinsert(self,v) end
+ return self
end
--- Insert an item at a given position. i is the index of the
-- element before which to insert.
-- @param i index of element before whichh to insert
-- @param x A data item
+-- @return the List
function List:insert(i, x)
- tinsert(self,i,x)
+ if x then tinsert(self,i,x) else tinsert(self,i) end
+ return self
end
--- equivalent of Python's _del s[i]_
-List.delete = tremove
+--- Equivalent of Python's _del s[i]_.
+-- @return the List
+function List:delete(i)
+ tremove(self, i)
+ return self
+end
--- Remove the first item from the list whose value is given.
-- Return nil if there is no such item.
-- @param x A data value
-function List:remove(x)
+-- @return the List
+function List:purge(x)
for i=1,#self do
- if self[i]==x then tremove(self,i) return end
+ if self[i]==x then tremove(self,i) return self end
end
+ return self
end
--- Remove the item at the given position in the list, and return it.
-- If no index is specified, a:pop() returns the last item in the list.
-- The item is also removed from the list.
+-- Alias: remove, like table.remove
-- @param i An index
function List:pop(i)
- if not i then i = #self end
- return tremove(self,i)
-end
+end -- for ldoc
+List.pop = tremove
+List.remove = tremove
--- Return the index in the list of the first item whose value is given.
-- Return nil if there is no such item.
@@ -166,15 +179,19 @@
--- Sort the items of the list, in place.
-- @param cmp an optional comparison function; '<' is used if not given.
+-- @return the List
function List:sort(cmp)
tsort(self,cmp)
+ return self
end
--- Reverse the elements of the list, in place.
+-- @return the List
function List:reverse()
local t,n={},#self
for i=1,n do t[i]=self[n-i+1] end -- reverse
for i=1,n do self[i]=t[i] end -- copy back
+ return self
end
local function normalize_slice(self,first,last)
@@ -183,7 +200,6 @@
if first<0 then first=sz+first+1 end
-- make the range _inclusive_!
if not last then last=sz end
- if last < 0 then last=sz+1+last end
return first,last
end
@@ -202,8 +218,10 @@
end
--- empty the list.
+-- @return the List
function List:clear()
for i=1,#self do tremove(self,i) end
+ return self
end
--- Emulate Python's range(x) function.
@@ -232,11 +250,13 @@
-- equivalent to 'del s[i1:i2]' in Python.
-- @param i1 start of range
-- @param i2 end of range
+-- @return the List
function List:chop(i1,i2)
i1,i2 = normalize_slice(self,i1,i2)
for i = i1,i2 do
tremove(self,i1)
end
+ return self
end
--- Insert a sublist into a list
@@ -244,21 +264,25 @@
-- @param idx index
-- @param list list to insert
-- @usage l = List{10,20}; l:splice(2,{21,22}); assert(l == List{10,21,22,20})
+-- @return the List
function List:splice(idx,list)
idx = idx - 1
for i,v in ipairs(list) do
tinsert(self,i+idx,v)
end
+ return self
end
--- general slice assignment s[i1:i2] = seq.
-- @param i1 start index
-- @param i2 end index
-- @param seq a list
+-- @return the List
function List:slice_assign(i1,i2,seq)
i1,i2 = normalize_slice(self,i1,i2)
if i2 >= i1 then self:chop(i1,i2) end
self:splice(i1,seq)
+ return self
end
--- concatenation operator .. .
@@ -336,6 +360,17 @@
return res
end
+--- Return the concatenation of all elements in the List. Like table.concat
+-- @sep Optional separator between the elements
+function List:concat(sep)
+end -- for ldoc
+List.concat = table.concat
+
+--- Find largest numeric index. Like table.maxn
+function List:maxn()
+end -- for ldoc
+List.maxn = table.maxn
+
--- Create an iterator over a seqence.
-- This captures the Python concept of 'sequence'.
-- For tables, iterates over all values with integer indices.