Feature request: subclassing FunctionType [Was: Some language proposals]

Jacek Generowicz jacek.generowicz at cern.ch
Mon Mar 1 04:07:53 EST 2004


michele.simionato at poste.it (Michele Simionato) writes:

> Jacek Generowicz <jacek.generowicz at cern.ch> wrote in message news:<tyfsmgtbewl.fsf at lxplus030.cern.ch>...
> > I think that you are misleading yourself. You are comparing apples to
> > quinces.
> 
> I thank you for the long post and the time you spent in clarifying the
> issue I had; however, you are speaking to a converted, since I already
> came to the same conclusion on my own (see my reply to Bengt Richter).

Ah, OK, sorry. Didn't see that one at the time I was writing.

> Still, I maintain that the ability to subclass FunctionType would be nice ;)

I agreed with you originally on that, and I still do :-)

Just one thing bothers me about your conclusions in your reply to
Bengt ...

[As my discussion turned out longer than I originally intended, let me
pull the summary up here to the top: 

  In short, the reason Scheme hides the "feature" is that there is no
  iteration in Scheme, only recursion.
]

michele.simionato at poste.it (Michele Simionato) writes:

> But still it is easy to forget that the helper function is needed
> and that using directly the lambda would not work. It is kind of
> error prone.

Don't think about helper functions, think about the scopes that are
intoduced. It's not the function that matters, it's the scope (the
inner binding), which in Python can only be introduced by nesting a
function, while in Scheme and CL you can use let.

> Scheme is less error prone since it uses local loop variables

The behaviour has nothing to do with globality or locality of the
variable which is used. It depends on whether the same binding is
being updated, or whether a new binding is being created each time
around the loop.

> and automatically generates separate closures:

Python also greates separate closures. Scheme (and Python when you
instruct it to do so) creates separate bindings of the same name so
that the binding found by the free variables in the closure is
different for each closure.

> (define list-of-adders '())
> 
> (let loop ((i 0))
>   (set! list-of-adders (cons (lambda (x) (+ x i)) list-of-adders))
>   (if (= i 1) 'exit (loop (add1 i))))
> 
> (define add1 (first list-of-adders))
> (define add0 (second list-of-adders))

[...]

> You can get Python behavior if you explicitely use a global variable:
> 
> (define list-of-adders '())
> (define i 0)
> 
> (let loop ()
>   (set! list-of-adders (cons (lambda (x) (+ x i)) list-of-adders))
>   (if (= i 1) 'exit (begin (set! i (add1 i)) (loop))))

In the second case you are updating the _single_ (global as it
happens) binding [(set! i (add1 i))]. In the first case you do (loop
(add1 i)) which certainly looks like it's passing the new value to a
function which will create a new binding (though I suspect that
there's some macrology behind the scenes). If, in the first case, you
were to introduce a local variable to the loop and use (set! i (add1
i)) to update it, just like you do to the global, you'd see the
closures sharing the same value again.

As I said before, iteration in Scheme is usually (always?) implemented
via recursion, so it's difficult create a loop with a genuine looping
variable.

If you used recursion to implement iteration in Python, you'd get the
same as in Scheme:

def make_adders(i):
    if i < 0: return []
    return make_adders(i-1)+[lambda x:x+i]

add0, add1 = make_adders(1)

print add0(0) # => 0
print add1(0) # => 1

        

In short, the reason Scheme hides the "feature" is that there is no
iteration in Scheme, only recursion.


Disclaimer: 

  I am no Scheme expert. There may well be Schemes which support real
  iteration, but I believe that the usual and even encouraged means of
  iterating in Scheme is via recursion. (Note, this is _not_ the case
  in Common Lisp.) Please correct me if you know this to be wrong.



More information about the Python-list mailing list