[Tutor] Why lambda could be considered evil

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Tue, 27 Aug 2002 12:46:09 -0700 (PDT)


On Tue, 27 Aug 2002, Erik Price wrote:

>
> On Tuesday, August 27, 2002, at 01:55  PM, Danny Yoo wrote:
>
> > If you have some free time, I'd recommend a book called "Structure and
> > Interpretation of Computer Programs".  It has a big lambda symbol on
> > the front cover --- surely, with it, we may be able to elucidate this
> > mystery! *grin*
>
> I've been recommended to this book before... actually I've heard of it
> in many places.  I'll have to check it out.  But -another- programming
> language!! ;)  (I'm still getting used to Python!)
>
> > In a language that fully supports lambda, there's no need for a
> > separate "function definition" syntax, because all we'd need to define
> > functions is variable assignment and that lambda function constructor.
>
> How is Python deficient compared with these languages?


Lambda in Python is specifically weakened to only allow one "expression"
in it --- it's only meant to be a shortcut way of constructing a quicky
throwaway function.  And Python makes a distinction between expressions,
like:

###
>>> 42
42
###

and statements, like assignment:

###
>>> the_answer = 42
###

It's that double-whammy combination of one-expression /
statements-are-not-expressions restriction that makes lambda fairly weak
in Python.



There are only a few statement types in Python, but they're pretty common,
like

    print
    if / elif
    variable name assignment (=)

which is why stuff like 'lambda x: print x' doesn't work in Python:
'print' isn't an expression, so it can't be used in a lambda.


Not that there aren't any benefits to separating statements from
expressions: it allows us to use a familiar assignment syntax when we do
keyword parameter stuff, like that cgi.parse_qs() example from a few days
ago.  But it does keeps us from using lambda to make any Python function:
Python's lambda just isn't powerful enough: it can't make any functions
that contain statements.




On the other hand, some languages make no distinction between "statements"
and "expressions", which make it easier to mix them together.  In Scheme,
for example, everything's an expression.  Something like this:

###  (Python)
def factorial(x):
    if x == 0: return 1
    return x * factorial(x-1)
###

would be difficult to write as a lambda.  However, we can do it easily in
Scheme, because Scheme's conditional isn't a statement, but an expression
that gives us a value back:

;;;  (Scheme)
(define factorial
  (lambda (x)
    (if (= x 0) 1
      (* x (factorial (- x 1))))))
;;;

which translates in English to "the name 'factorial' will stand for this
function that takes one parameter 'x'."  So the tools that a Scheme
programmer has are smaller and simpler, which is very alluring to someone
who likes purity.



But here is one evil expression that involves lambda in a terribly
convoluted way:

;;;  (Scheme)
((lambda (kickstart-function x) (kickstart-function x kickstart-function))
 (lambda (y self-function)
   (if (= y 0) 1
     (* y (self-function (- y 1) self-function))))
 5)
;;;

Try guessing what that bit of code is doing, but don't stare at it too
long.  *grin* If it helps, and if you have a scheme interpreter like
'guile' on your system, you can vary the number at the bottom.



The fact that Scheme's lambda can be composed like this, and that
everything is an expression, is both a blessing and a curse --- in Scheme,
that language permits all expressions to mix well with each other...
sometimes too well.

But by forcing a wedge between statements and expressions, the Python
language tries to bound the complexity of any expression in Python to
something humanly managable.  So Python's lambda is weak for practical
reasons.



> Does this restrict a person from using "functional programming" in
> Python?

No, no, but it does reduces the power of using 'lambda' when we do
functional programming, placing it more in the 'def' statement.  When we
do functional programming in Python, we find outselves having to use 'def'
to be able to use statements in our functions.


Again, I hope some of this made some sense.  *grin*