[Tutor] List comprehension

alan.gauld@bt.com alan.gauld@bt.com
Sun, 27 Jan 2002 19:45:35 -0000


> As an application I really like defining gcd(a,b) and then
> gathering totatives (positives relatively prime to N and < N)
> by going:
> 
>   >>> def gcd(a,b):
> 	 while b:
> 	    a,b = b, a%b
> 	 return a
> 
>   totatives = [t for t in range(1,N) if gcd(t,N)==1]
>
> The lambda form would be:
> 
>    >>> filter(lambda a: gcd(a,28)==1,range(28))
>    [1, 3, 5, 9, 11, 13, 15, 17, 19, 23, 25, 27]
> 
> I don't find that any clearer than the list comprehension
> way of doing it.

But let's stop confusing two distinct structures.
The lamda form is a diffrent way of defining a 
function object - one with no name.

If you can create a named function(like gcd) then lambda is
not needed, so the "equivalent" form could be:

def gcd(a,b=28):
 	 while b:
 	    a,b = b, a%b
 	 return a == 1
   
filter(gcd, range(28))

lambda is only used as a quick n dirty way of defining 
a short function inine. Its not a necessary part of 
the map/filter/reduce syntax.

The Lisp take on Lambdas is that every block of code 
is essentially a lambda block and every function is 
merely a name referring to a lambda.

This in Lisp there is no difference between declaring 
a variable assignment and a function assignment:

(define foo 8)
(define bar (lambda x (+ x x)))

Are completely consistent. Both expressions simply assign 
a value (8 and a lambda respectively) to a name
(a variable if you like). That's why Lispers like lambdas 
because they bring consistency to the language.

But the FP functions do not rely on lambdas, they rely 
on function objects which is a different and more 
powerful concept. Thus knowing Lisp makes lambdas readable
but is not the reason I prefer map etc. I simply find:

map(f, Lst)

easier to read than

[f for i in Lst]

Partly coz my brain automatically parses the latter as

(f for i) in Lst

Which makes no sense! Thus I have to consciously back 
out and think the construct thru.

Thats why I'd have liked a separator of some sort 
between the expression and the for

>    >>> reduce(add,[a*b for a in [400,20,3] for b in [300,20,1]])
>    135783
>    >>> 423*321
>    135783

Now this is where I think LCs really do start to have 
an advantage even if I don't like the syntax.

Alan G