Hacker News new | ask | show | jobs
by Jtsummers 1378 days ago
Creating a new one. It isn't a closure, so:

  x = 3
  def f(x): # note the name here
    x = 20
  f(x)
  x # => 3
Similarly, using a different parameter name:

  def g(y):
    x = y
  g(20)
  x # => 3
You have to explicitly mark the `x` in the function to be the global one to reference it:

  def h(y):
    global x
    x = y
  h(10)
  x # => 10
With a lambda it would be a closure:

  i = lambda y : x # throwing away y for fun
  i(3) # => 10
  x = 20
  i("hi") # => 20
2 comments

No, I mean this:

  def f(x):
    g = lambda : x
    x = 2
    return g()

  f(42)
What is does f(42) return?

Holy fuck, I simply cannot just cut and paste the above into Python as-is, because of the "unexpected indent" which I added so that HN shows that as quote. It's complaining about an unexpected indent.

Kill. Me. Now.

Anywway:

  >>> def f(x):
  ...   g = lambda : x
  ...   x = 2
  ...   return g()
  ... 
  >>> f(42)
  2
So what it looks like is that there is only one x in the function, established by the parameter. This x is captured by the lambda, and is then reassigned the value 2. The lambda retrieves the 2.

For completeness we show that if x is not assignmed, g accesses f's argument value:

  >>> def f(x):
  ...    g = lambda : x
  ...    return g()
  ... 
  >>> f(42)
  42
`f` behaves just like closure. It can even be assigned to a variable.

    def f(x): x = 2 # <- this `x` is the same `x` as in the argument, it can be access via locals() internally

You can even assign `f`. For example, `function = f`.

Python is call by reference. Change my mind. `def f(x): x[0] = 1` will manipulate whatever object you pass to it.

If Python were fully call by reference then:

  def g(y):
    y = 3
  x = 10
  g(x)
  x # => ??
If it's 3 then it's pass by reference here, if it's 10 it's pass by reference. Which is it?

Additionally, for something to be a closure it has to close over something (an environment). What does `f` or `g` close over? Note that they aren't changing any environment, they are "merely" functions, not closures. Python does have closures, but those aren't examples of them.

And being able to assign a function to a variable does not make a closure, or do you think that C has closures because it has function pointers?

Oops:

If it's 3 then it's pass by reference here, if it's 10 it's pass by value. Which is it?

(Don't hit reply when you're rushing out the door.)

> Python is call by reference. Change my mind.

No need to change your entire mind; just an incorrect definition of call-by-reference.

Passing a value which has reference semantics isn't call-by-reference.

Your f receives x by value. That value is a reference into a boxed object. The x[0] = 1 does not change x; it changes the boxed object.

  >>> def f(x):
  ...    x[0] = 1
  ... 
  >>> a = [ 0, 2, 3 ]
  >>> b = a
  >>> f(a)
  >>> a is b
  True
The f function can do nothing to make "a is b" false.

Under pass-by-reference, assigning to x would do that.

Under pass-by-reference, we can pass a reference to a, such that a can be replaced, without affecting b.

"pass-by {whatever}" refers to the semantics of the parameter and what it receives from the argument expression, and how, not the semantics of the argument object/value.