Python doesn't even have closures.
> Interpreted
Languages are neither interpreted nor compiled. Implementations are.
Python doesn't even have closures.
> Interpreted
Languages are neither interpreted nor compiled. Implementations are.
The usual reason people give for believing this is the inability to mutate closed-over variables.
If that's the case, then a strictly-immutable FP language similarly "wouldn't have closures" and thus could not be FP. Problem solved!
def some_function(val):
def say_stuff():
print("message is: {}".format(val))
def mutate_me(new_mutation):
nonlocal val
val = new_mutation
say_stuff.mutate_me = mutate_me
return say_stuff
if __name__ == '__main__': f = some_function("hello")
f.mutate_me("goodbye")
f()So what's this?
>>> x = 1
>>> def f(y): return y + x
...
>>> f(2)
3
EDIT: Note that my example works even if the definition of x and f appear within the definition of another function. If closed-over variables must be mutable then Haskell doesn't have closures!Closures define the set of variables whose lifetime extends the function they are in because of their use in another function.
For instance:
;; Function that returns a function that counts even numbers
(define (even)
(let ((x 0))
(lambda () (set! x (+ x 2)) x)))
(define count (even))
(count) ; → 2
(count) ; → 4
In Python: def even():
x = 0
def add():
x += 2
return x
return add
count = even()
count() # → UnboundLocalError: local variable 'x' referenced before assignment
That said, Python does support a less convenient style of closures — it works if the variable is a container (such as a list, a dictionary or an object). def add_double(n):
x = n * 2
def add(y):
return x + y
return add
f = add_double(1)
f(2) # -> 4
What python versions prior to 3 didn't support is rebinding a variable from an enclosing scope; not because of any fundamental feature of the implementation, but because there was no syntactic way to differentiate between a assigning to a variable in an enclosing scope, and creating a variable in the current scope. So x += 2 is short for x = x + 2, which python interprets as creating a new variable x in the current scope and then trying to access that variable before it's been assigned.Python 3 introduced a syntax to specify that you wanted to assign to a variable from an enclosing scope, the 'nonlocal' keyword. So your example would be:
def even():
x = 0
def add():
nonlocal x
x += 2
return x
return add
count = even()
count() # → 2
count() # → 4 #include <stdio.h>
int x = 1;
int f(int y) {
return x + y;
}
int
main(argv, argc) {
printf("f(2): %i\n", f(2));
}
The reason they are called closures is because they close over the, lexical, environment where the function was defined.Python doesn't have lexical scope, hence it doesn't have closures.
Can you explain why https://en.wikipedia.org/wiki/Python_syntax_and_semantics#Cl... says:
> Python has had support for lexical closures since version 2.2. ... Python's syntax, though, sometimes leads programmers of other languages to think that closures are not supported. Variable scope in Python is implicitly determined by the scope in which one assigns a value to the variable, unless scope is explicitly declared with global or nonlocal.
?
More over here - http://stackoverflow.com/a/23558809/171450
I.e.,
Python 3.4.3 (default, Apr 7 2015, 08:05:21)
>>> def mk_generator(initial):
... var = initial
... def increment(count=1):
... nonlocal var
... var += count
... return var
... return increment
...
>>> a = mk_generator(3)
>>> b = mk_generator(10)
>>> a(1)
4
>>> b
<function mk_generator.<locals>.increment at 0x1040a7d08>
>>> b()
11
>>> b()
12
>>> a(3)
7