Python is Considered Harmful

Matthias Felleisen matthias at ccs.neu.edu
Mon Oct 27 21:37:49 EST 2003


Jeremy Fincher wrote:

> Expected by functional programmers who expect new lexical scopes to be
> created at every block, sure.  But Python isn't a functional
> programming language, and doesn't create a new lexical scope in every
> block.
>  
> The Python result is only surprising to those who try to impose other
> languages' semantics on Python.

Yes, that's true but functional programmers come from a "carry your semantics
on your sleave" angle at things. Let's see how we build this in Scheme. If I 
understand Python's semantics properly, a for-iterator has this semantics:

(define-syntax python-for
   (syntax-rules (in range)
     [(_ x in (range n) exp ...)
      (let ([x #f])
        (for-each (lambda (i) (set! x i) exp ...) (build-list n identity)))]))

It sets up an iteration variable and then mutates the iteration variable for
each iteration. Then you evaluate the body of the for. A Schemer wouldn't cut
the overhead and write/expect something like that:

(define-syntax scheme-for
   (syntax-rules (in range)
     [(_ x in (range n) exp ...)
      (for-each (lambda (x) exp ...) (build-list n identity))]))

Here we just iterate over the specified variable. (I have the iteration order of 
the number sequence backwards. That's intended to skip a small bit of syntactic
overhead.)

Now depending on which of these for's you use you get different results for

(define flist '())

(define f #f)

(for i in (range 3)
      (set! f (lambda (x) (+ x i)))
      (set! flist (cons f flist)))

(map (lambda (f) (f 1)) flist)

Nothing surprising here for someone who studies language semantics. Things are 
as they are. But to someone who compares these things, I must admit that I am 
astonished that Python chose the first, complicated (not on your sleave) 
semantics and rejected the second one.

-- Matthias







More information about the Python-list mailing list