lua-users home
lua-l archive

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


On Sat, Apr 25, 2009 at 4:00 AM, steve donovan wrote:
> On Sat, Apr 25, 2009 at 9:17 AM, David Manura wrote:
>> for k in pl.list.iter(List(tablex.keys(t)):sort()) do
>>   print(k,t[k])
>> end
>> That's a bit ugly.

That would be nicer if the API allowed method call chaining:

  for k in List.keys(t):sort():iter() do
    print(k,t[k])
  end

That would follow a useful pattern of

  (1) wrap a table into a list ... e.g. List(t) or List.keys(t)
  (2) chain any number of list operations ....
       e.g. :sort(f):map(g):filter(h)
  (3) convert to a sequence to iterate over
       (It would be preferable if this could be avoided as in Python,
        defaulting to the type of iteration we usually want.
        An __iter metamethod has been proposed:
        http://lua-users.org/wiki/GeneralizedPairsAndIpairs )

>> If the sort didn't have to be in-place, we could chain the
>> transformations on a single line:

In-place v.s. non-in-place operations...Penlight currently departs
from its Python inspiration in that it provides additional List
methods like "map/filter" that are not in-place like its methods
"sort/reverse".  This feels inconsistent/arbitrary.  Python
not-in-place operations are separated out as standalone functions:
"sorted/map/filter".

However, consider the approach in Chapter 16 of Lua Programming Gems
used to implement a matrix type (p.180).  All operations (even map)
are in-place, like Python list methods.  However, there is an explicit
copy() method, and all operations return the object itself to allow
chaining.

  -- two different uses
  return a:copy():emwul(b):linfold()
  return a:emwul(b):linfold()

This is flexible and avoids excessive temporary copies.

In fact, Penlight already does the copy when constructing a list from a table.

> Python makes the consequence of sequence
> more explicit, whereas it isn't really a native Lua concept.  There is
> for instance both seq.reduce and tablex.reduce

Shouldn't there also be a List:reduce?

> whereas a smart reduce
> could work out from its arguments what operation was required.

Perhaps.

>> I'm not certain I like your argument order for functions though.
>
> Yes, I was being deliberately backwards.  But if we are _mostly_ using
> prepackaged functions, then the argument is moot. The concern was that
> when using the traditional order, the actual
> table/sequence/list/whatever ends up at the end of a potentially long
> anonymous function definition.
>
> t1 = map(function(x)
>           return x*(x-1)
>     end,t1)

The problem I think is when we chain these operations together:

  t1 = sort(map(filter(t1, f), g), h)

Now, "h" modifies the verb "sort", "g" modifies "map", and "f"
modifies "filter".  These are farther apart and read less naturally
than if we had written

  t1 = sort(h, map(g, filter(f, t1)))

We can also compose and curry them:

  t1 = compose(curry(sort,h), curry(map,g), curry(filter,f))(t1)

On the other hand, the form map(t, f) is useful when map a method of
list, list:map(f), rather than a standalone function.