[BangPypers] Does Python have lexical scoping?
anandology at gmail.com
Mon Nov 10 08:04:22 CET 2014
On Mon, Nov 10, 2014 at 12:17 PM, Anand Chitipothu <anandology at gmail.com>
> 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
>> x = 2
>> def f(y): return x + y
>> x = 10
>> 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.
> There are cases where both lexical scope and dynamic scope produce same
> results. The example that you gave falls into that category.
Sorry, forgot to add the output.
> Try the following example:
> (setq x 5)
> (defun getx () x)
> (defun f (x) (getx))
> (f 10)
prints 10, the x from function f, not global x.
> (setq x 4)
> (f 10)
prints 10 again. changing the global x don't have any affect.
Python or scheme (lexical scoping) would produce 4 in this case.
> 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)
prints 3. Picks x from 2 stack frames below.
> 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.
More information about the BangPypers