
What’s the issue with Python’s scope story? I haven’t used Python much, so I can’t draw many conclusions about it.

def f(b):
if b:
x = 1
print(x)

Does this cause a compile-time error? If not, what happens when you execute f(True)
and f(False)
?

Oh, that’s dreadful.

I would hope they Python folks went with the sane decision of making that a static error.

Then again, it’s my understanding that everything in Python is a dictionary, so it could be argued that it should be a dynamic error.

Either way, that’s awfully confusing.

They should silently change def
to be interpreted as d*e*f,
that would be fun

f(True)
prints 1
f(False)
raises an UnboundLocalError

A related bug report I received recently: https://github.com/Bogdanp/dramatiq/issues/382

Shame on me for writing the code the way that I did. Shame on Python for letting me :sweat_smile:


This is pretty technical, but the tldr is it’s not as simple as environments and lexical scoping.
https://cs.brown.edu/~sk/Publications/Papers/Published/pmmwplck-python-full-monty/

back in the days when I wrote a lot of python 2.x code, I had to always keep in mind some of python’s scoping issues.

Technically, Python almost has “lexical scope.”
The only place it doesn’t use lexical scope is at top-level. The behavior inside a function, on the other hand, is due to hoisting (in the same fashion as JS). Not lexical like Scheme, but lexical enough.

Right. I was also thinking about how there isn’t implicit scope in places where a user (or just me?) may expect like conditional bodies.

Yeah. Hoisting is evil. To me, having lexical scope is not enough.

Hoisting?

In JS, this program:
function f(b) {
if (b) {
var x = 1;
}
console.log(x);
}
is similar to the Python program I posted earlier, but if b
is false
, it results in undefined
.
The way it works is that the program is first transformed into:
function f(b) {
var x = undefined;
if (b) {
x = 1;
}
console.log(x);
}
This transformation process is known as hoisting. It lifts variable declaration up.

Python is similar:
def f(b):
if b:
x = 1
print(x)
is transformed to:
def f(b):
x = <error if referenced>
if b:
x = 1
print(x)

That’s a confusing transformation to perform on a program.

Apparently it’s a beloved transformation for cool languages :slightly_smiling_face:

I’ll gladly stay in the uncool language camp, then :stuck_out_tongue: