new 1.0 Beta features and impressions

Steven D. Majewski (sdm7g@elvis.med.virginia.edu)
Wed, 19 Jan 1994 14:38:26 -0500

Well, I like 'map' and 'filter' and 'lambda'.

At first I was a bit annoyed at the limitations of 'lambda' - it seems
to only be able to handle simple expressions - but then I realized that
I didn't really need an 'if' statement in most cases - just the boolean
part of it:

filter( lambda x : ( 3 < x < 12 ), list )

*NOT* "lambda x: if ( 3 < x < 12 ) ... "

So now that I've figured out how to use it, I'm happy.

I think the transpose that map( None, [1,2,3],[10,20,30] ) does
it a handy feature.

It *is* a bit awkward that 'apply' requires a tuple and won't
take any other sequence. This has, of course, been a requirement
of 'apply' since it was introduced - ( when ? I don't know when
it made an appearance, but it was there well before the 1.0 additions
of 'lambda','map','filter'. ) - and it looks like it is not an
arbitrary test, so much as a side effect of the fact that 'apply'
is reusing the interpreter-code, which was only designed to handle
tuples. I never noticed it as a problem before, as the primary use
of apply was in code that used the *varargs convention and needed
to call another function/method with all of IT's args. Now that
I have 'map', it seems natural to string them together in some
cases - which is where I bumped into that restriction.

I was trying to make a sum-of-products function that takes a
variable number of sequences and returns
Sigma-sub-n: s1[n] * s2[n] * ... * sm[n]
I don't remember WHAT I was trying to do yesterday that didn't
work, but what I have now that does work is:

def prod( *t ):
p = 1
for x in t: p = p * x
return p

def sum( seq ):
s = 0
for x in seq: s = s + x
return s

def SumOfProd( *S ):
return sum( apply( map, ( prod, ) + S ) )

I think I was trying to find some way of avoinding the asymetry of
"prod( 1,2,3 )" versus "sum( [1,2,3] )" .

BTW: Now a quickie way to format your dictionaries for pretty-printing is
(something like):

from string import rjust,ljust,joinfields

print '{\n'+joinfields( map( lambda x: rjust(str(x[0]),10)+':'+str(x[1]),
dict.items()), ',\n' ) + '\n}'

O.K. - The above could almost as easily been done using 'for'.
A *better* example would be pasting columns of text ( represented
as lists of strings ) together.

Just as 'for' is the natural way to process A single sequence,
'map' seems a much more natural way to think about dealing with
several sequences, element by element, than the typical 'for'
alternative ( for i in min( len(seq1), len(seq2), len(seq3) ):
out.append( f(seq1[i],seq2[i],seq3[i] ) )

[ But maybe I'm contaminated by lisp thinking - I've been trying
to use Xlisp-stat. It's nice, but having to type:
'( select seq ( iseq n m ) )'
instead of Python's:
'seq[n:m]'
reminded me of some of the things I don't like about Lisp.
( as well as the thinks I DO like! )

But I don't have time to rewrite the stat library into Python,
and I'ld need to get the X interface ported (reliably) to AIX. :-(

BTW: I've been following comp.lang.dylan, and it looks like
the standard syntax for Dylan is going to be an "algol-ish"
rather than a "lisp-ish" one. Python is growing more and more
"lisp-ish" with lambda, map, eval, apply, ... etc. and I
won't be too suprised if Dylan ( Firmly in the Lisp/Scheme
family tree ) doesn't end up looking rather "Python-ish" ! ]

- Steve Majewski (804-982-0831) <sdm7g@Virginia.EDU>
- UVA Department of Molecular Physiology and Biological Physics