Skip to content

Latest commit

 

History

History
139 lines (99 loc) · 4.16 KB

mep-0002.md

File metadata and controls

139 lines (99 loc) · 4.16 KB
MEP Title Discussion Implementation
2
Local Variables
XXX

Local Variables

Abstract

This MEP proposes syntax and semantics for variables that are local to a cell. Variables declared with a single leading underscore, such as _x or _ (but not starting two underscores] __) are not added to a cell's list of definitions, and are unavailable to other cells.

Motivation

The rule against declaring the same global name in multiple cells can be unwieldy, since some names may be declared at a cell's top-level scope but meant only to be used within the cell as an internal or private variable.

Underscore. An important example is the underscore identifier _, used to communicate that a value is unused: e.g.,

_, value = f()

Loop variables. Another important example class are loop variables:

for i in range(10):
   ...

Because scoping in Python is leaky, i becomes a global variable, even though in most cases the programmer won't ever read i after the loop body. This same problem arises in with statements.

Temporaries. A name may be used to bind to a temporary or intermediate value in a computation to minimize redundant computation or for legibility of the code:

b = X @ a
c = Y @ b
d = Z @ b

Here, perhaps c and d will be used by other cells, but b won't.

Proposed Syntax

Any name that begins with an underscore is treated as a local variable.

Examples:

Unpacking.

_, value = f()

Here _ starts with an underscore, so it is a local variable.

Loop variables.

for _i in range(10):
   ...

Temporaries.

_b = X @ a
c = Y @ _b
d = Z @ _b

Representation in the generated module

Variables prefixed with _ will not be included in the returns of a cell's defining function.

Discussion

The syntax follows the familiar idiom of using leading underscores to designate a variable as private, and it includes the conventional use of _ as a temporary identifier as a special case.

The syntax makes an exception for names starting with two underscores to prevent conflicts with system names (like __name__, __builtins__, etc) which typically start with two underscores.

It can be awkward or ugly to prefix variables with underscores. If a programmer finds that they have to do this very often within the same cell, they could instead opt to encapsulate their code within a function (which they may choose to make local), removing the need to prefix the variables.

Sometimes one may actually want a name starting with _ to be available to all cells.

  • Imported names may start with _. These imported names would need to be aliased to make them available throughout the entire app.
  • The programmer might want names starting with _ to be internal to their app, not internal to their cell. In this case, they would need to make internal names start with two underscores instead of one.

Alternatives Considered

Double leading underscore. Treat names with double leading underscores as private, instead of a single leading underscore. This mitigates the conflict with traditional naming conventions (with single leading underscore used for internal to app, instead of internal to cell), but does not allow for using _ as a temporary.

Variable annotation. An alternative to name-based designation of locals is to use a variable annotation, such as

i: mo.local

This may lead to more legible typography, since code will not be cluttered with underscores. But it is unidiomatic, and does not cover the use of _ as a temporary identifier. Moreover, it leads to ambiguity in the case that another cell declares i as a global varible.

No local variables. We could choose to not have any local variables, but provide a special case for _. Users would then be very strongly encouraged to encapsulate code in functions. But they wouldn't be able to make local functions, pushing the naming problem from variables to functions.

Implementation

https://github.com/marimo-team/prototype/tree/locals

  • Modify the AST visitor to mangle names (ast.Name nodes, and identifier strings)