lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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.