Fate of lambda, Functional Programming in Python...

Michael J. Fromberger Michael.J.Fromberger at Clothing.Dartmouth.EDU
Sun Aug 22 00:49:43 CEST 2004


In article 
<87y8k9hqnq.fsf at debian.i-did-not-set--mail-host-address--so-shoot-me>,
 510046470588-0001 at t-online.de wrote:

> Marek <imbaczek-nospam at poczta.fm.cut-from-here.no-spam.info> writes:
> 
> may map, filter, reduce be implemented in pure python if they weren't 
> built-in? scheme e.g. does not have built-in filter, but may 
> implement it on the fly.

I do not see any reason why not.  Simple map and filter implementations 
for lists are almost trivial given list comprehensions.  But, you do 
have to be slightly careful of return types; I think the following 
implementations are correct:

  def map(fn, *lsts):
    assert(len(lsts) > 0)
    
    return [ fn(*args) for args in zip(*lsts) ]

  def filter(fn, seq):
    if fn is None:
      out = [ x for x in seq if x ]
    else:
      out = [ x for x in seq if fn(x) ]
    
    if isinstance(seq, str):
      return str.join('', out)
    else:
      return type(seq)(out)

Reduce is a little bit harder to get exactly right, because of the 
semantics of the initial value.  However, I do think the following does 
most of what reduce() is supposed to, even though it is not quite 
equivalent to the existing reduce():

  def reduce(fn, seq, init = None):
    seq = iter(seq)
    
    if init is None:
      try:
        init = seq.next()
      except StopIteration:
        raise TypeError("reduce() of empty sequence "
                        "with no initial value")
    
    for elt in seq:
      init = fn(init, elt)
    
    return init

To perfectly emulate the built-in reduce, you would have to declare it 
as reduce(fn, *args), to distinguish between the case when the user 
omitted the init argument, and when they actually specified it as None.  
That makes the code nastier, of course.

> may lambda be implemented with exec if it isn't built-in?

Not directly; the lambda form is currently wired into the syntax, and 
there is no macro system.  Scheme (and other Lisp dialects) can get away 
with a lot fewer built-in special forms because of the relative ease of 
writing macros.  Macros for an infix language are not impossible, by any 
means, but they are definitely not easy (and definitely not "Pythonic").

I would prefer to see an expression-level function constructor to remain 
in the language.  I don't care if it's called "lambda" per se, and I 
don't care if the syntax changes, but I would definitely like to keep 
the functionality around.  Now that there ARE nested scopes, it seems 
that Guido's initial objections to the construct are mostly moot.

-M

-- 
Michael J. Fromberger             | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/  | Dartmouth College, Hanover, NH, USA



More information about the Python-list mailing list