8

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!

Mihai Vinaga
  • 1,059
  • 2
  • 10
  • 27

2 Answers2

7

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.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • Well, you could also say that in ML, variables are also captured by reference -- variables cannot be assigned to in ML, so whether variables are captured by value or by reference makes no difference. – newacct Oct 28 '13 at 02:48
  • Yeah, I don't know enough about ML to say anything about it. :-) – kindall Oct 28 '13 at 02:50
6

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.

Nick Barnes
  • 19,816
  • 3
  • 51
  • 63
  • 1
    There is no variable assignment in ML, period. (There is simply not even a syntax for assigning to a variable.) You can have references to mutable data structures, and you can modify that data structure. But you cannot assign to a variable. – newacct Oct 28 '13 at 16:38