I'm in a big dilemma, take the following code written in ML:
val x = 1
fun f(y) = x + y
val x = 2
val y = 3
val z = f (x + y)
The value of z is 6. Now if I write the same code in python the value of z would be 7. And both languages claim(actual the teachers that teach these languages claim this) to have Lexical / Static scope. But it looks like only ML has it by using the environment that was creating when the f function was defined whenever f is called
Any pointers would be greatly appreciated!
Thanks!
I'll use that. JavaScript and other languages such as the C family and Python use lexical scope , also called static scope , which means that scope nests according to where functions and variables are declared.
The lexical scope allows a function scope to access statically the variables from the outer scopes. Finally, a closure is a function that captures variables from its lexical scope. In simple words, the closure remembers the variables from the place where it is defined, no matter where it is executed.
Lexical scoping, also known as static scoping, is a convention used with many modern programming languages. It refers to setting the scope, or range of functionality, of a variable so that it may be called (referenced) from within the block of code in which it is defined.
Python uses lexical scoping, there is no dynamic scoping.
In Python, closures are by variable, not by value. So when you refer to x
in a function, it refers to the most recent value assigned to x
, not to the value of x
when the function was defined. This gets non-intuitive results like the one below:
adders = []
for x in range(10):
adders.append(lambda y: x+y)
You intend to make a list of functions that add x
to a value, where x
varies from 0...9, but instead they all add 9 because that's the value of x
at the end of the loop.
You can override this by using a default argument to bind the name to its value at the time of the function definition.
x = 1
f = lambda y, x=x: x + y # x inside f is now locked at 1
x = 2
y = 3
z = f(x + y)
In this example you're not even actually dealing with a closure: x
here is actually a global variable. In Python, a closure can be created only when a function is defined inside another function, and the top-level or module-global namespace is not a function. But the same principle applies: the global variable can obviously be changed after the function is defined, so if you want to "lock in" its value at the time of function definition, you use a default argument.
In ML - at least, in the functional part of ML - there is no such thing as variable assignment. Once you have declared that val x = 1
, you can't change the value of that x
.
What you can do, however, is declare another x
. When you say val x = 2
, you're introducing a brand new variable called x
, which basically just hides the old one. But the function f
has already been defined to point to the original x
, so it's not affected.
ML does support mutable types, which can be reassigned just like variables in Python. But they stray so far from the functional paradigm that you should rarely have any reason to use them. If you want to program like that, Python's a far better language for it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With