Skip to content

Commit

Permalink
spec: clarify scope rules for comprehensions
Browse files Browse the repository at this point in the history
- first loop operand is resolved in enclosing environment
- all loop vars are bound before any expression is resolved

See bazelbuild/starlark#84

Change-Id: I2c4283719cf78cea27dccba1ffb0932857254909
  • Loading branch information
adonovan committed Jul 31, 2020
1 parent f21d2f7 commit 42cae68
Showing 1 changed file with 26 additions and 1 deletion.
27 changes: 26 additions & 1 deletion doc/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,6 @@ def hello():
if x == 1:
y = "hello"
```

It is a dynamic error to evaluate a reference to a local variable
before it has been bound:

Expand All @@ -1319,6 +1318,32 @@ print(x) # dynamic error: global variable x referenced before ass
x = "hello"
```

and for nested loops in comprehensions.
In the (unnatural) examples below, the scope of the variables `x`, `y`,
and `z` is the entire compehension block, except the operand of the first
loop (`[]` or `[1]`), which is resolved in the enclosing environment.
The second loop may thus refer to variables defined by the third (`z`),
even though such references would fail if actually executed.

```
[1//0 for x in [] for y in z for z in ()] # [] (no error)
[1//0 for x in [1] for y in z for z in ()] # dynamic error: local variable z referenced before assignment
```

<!-- This is similar to Python[23]. Presumed rational: it resembles
the desugaring to nested loop statements, in which the scope
of all three variables is the entire enclosing function,
including the portion before the bindings.
def f():
...
for x in []:
for y in z:
for z in ():
1//0
-->


It is a static error to bind a global variable already explicitly bound in the file:

```python
Expand Down

0 comments on commit 42cae68

Please sign in to comment.