[BangPypers] Does Python have lexical scoping?

Anand Chitipothu anandology at gmail.com
Mon Nov 10 07:47:16 CET 2014


On Sun, Nov 9, 2014 at 10:38 AM, Noufal Ibrahim KV <noufal at nibrahim.net.in>
wrote:

>
> Okay, I've been struggling through the proglang course on coursera and
> this thing came up
>
>    val x = 2;
>    fun f y = x + y;
>
> The second line creates a function that adds `x` to it's argument. Since
> ML is statically scoped, this is really a function that adds 2 to its
> argument.  Even if I later create a new binding for x later like so
>
>    val x = 10;
>    f (3);
>
> I will still get back 5 (i.e. 2 + 3) instead of 13 (10 + 3). This makes
> sense to me as an example of lexical scoping. The bindings are at the
> time of definition rather than invocation.
>
> With python, it's different. The claim is that it has lexical scoping
> but.
>
>      x = 2
>      def f(y): return x + y
>
>      x = 10
>      f(3)
>
> The answer is, distressingly, 13. The explanation was that although
> Python has lexical scoping, that closure "close over variables rather
> than values". Meaning that the variables (and not their values) at
> definition time are stored in the closure. This is how elisp does it
> which claims to be, by default, dynamically scoped.
>
> (setq m 5)
> (defun test (x)
>   (+ x m))
>
> (test 3) ; -> 8
> (setq m 15)
> (test 3) ; -> 18
>
>
> So, my question is, how different is this from dynamic scoping (like in
> elisp) where the values are actually picked up from the execution
> (rather than definition) environment. This business of "closes over
> variables rather than values" sounds like a cop out.
>
> Comments?
>

There are cases where both lexical scope and dynamic scope produce same
results. The example that you gave falls into that category.

Try the following example:

(setq x 5)
(defun getx () x)
(getx)

(defun f (x) (getx))

(f 10)
(setq x 4)
(f 10)

The function getx takes the values of x that is closest to in the stack,
not the one that is lexically closest.

Another example to demonstrate that.

(defun g (x) (h x))
(defun h (y) (getx))
(g 3)

With lexical scoping a can be resolved at the time of declaring the
function it self (as in name x in getx is alias to x defined in the
top-level), where as with dynamic scoping it can only be determined at the
run time. Because of this lexical scoping is usually faster.

Anand


More information about the BangPypers mailing list