In some languages, however, "part of a program" refers to a portion of run time (period during execution), and is known as dynamic scope.
In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context (also called static context), which is defined by where the named variable or function is defined.
De facto dynamic scope is common in macro languages, which do not directly do name resolution, but instead expand in place.
In languages like C++, accessing an unbound variable does not have well-defined semantics and may result in undefined behavior, similar to referring to a dangling pointer; and declarations or names used outside their scope will generate syntax errors.
For example, in Standard ML, if f() returns 12, then let val x = f() in x * x end is an expression that evaluates to 144, using a temporary variable named x to avoid calling f() twice.
As the variable names in the prototype are not referred to (they may be different in the actual definition)—they are just dummies—these are often omitted, though they may be used for generating documentation, for instance.
A subtlety of several programming languages, such as Algol 68 and C (demonstrated in this example and standardized since C99), is that block-scope variables can be declared not only within the body of the block, but also within the control statement, if any.
In this example, inside the block the auxiliary variable could also have been called n, shadowing the parameter name, but this is considered poor style due to the potential for errors.
This is properly understood in the context of dynamic dispatch rather than name resolution and scope, though they often play analogous roles.
In some cases both these facilities are available, such as in Python, which has both modules and classes, and code organization (as a module-level function or a conventionally private method) is a choice of the programmer.
This is a property of the program text and is made independent of the runtime call stack by the language implementation.
Static scope allows the programmer to reason about object references such as parameters, variables, constants, types, functions, etc., as simple name substitutions.
In contrast, dynamic scope forces the programmer to anticipate all possible execution contexts in which the module's code may be invoked.
Depending on implementation and computer architecture, variable lookup may become slightly inefficient[citation needed] when very deeply lexically nested functions are used, although there are well-known techniques to mitigate this.
[9][10] Also, for nested functions that only refer to their own arguments and (immediately) local variables, all relative locations can be known at compile time.
Deep binding, which approximates static (lexical) scope, was introduced around 1962 in LISP 1.5 (via the Funarg device developed by Steve Russell, working under John McCarthy).
The so-called "FUNARG problem"[12][13] is completely solved, in both the downward and upward cases.By the same year in which An overview of Common LISP was published (1982), initial designs (also by Guy L. Steele Jr.) of a compiled, lexically scoped Lisp, called Scheme had been published and compiler implementations were being attempted.
Introducing a local variable with name x pushes a binding onto the global x stack (which may have been empty), which is popped off when the control flow leaves the scope.
However, since a section of code can be called from many different locations and situations, it can be difficult to determine at the outset what bindings will apply when a variable is used (or if one exists at all).
Some languages, like Perl and Common Lisp, allow the programmer to choose static or dynamic scope when defining or redefining a variable.
[18] Shallow binding is an alternative strategy that is considerably faster, making use of a central reference table, which associates each name with its own stack of meanings.
The local binding is performed by saving the original value in an anonymous location on the stack that is invisible to the program.
Dynamic scope provides an excellent abstraction for thread-local storage, but if it is used that way it cannot be based on saving and restoring a global variable.
When the initial, outermost override's context terminates, the thread-local key is deleted, exposing the global version of the variable once again to that thread.
In modern languages, macro expansion in a preprocessor is a key example of de facto dynamic scope.
Properly, the C preprocessor only does lexical analysis, expanding the macro during the tokenization stage, but not parsing into a syntax tree or doing name resolution.
Some languages have mechanisms, such as namespaces in C++ and C#, that serve almost exclusively to enable global names to be organized into groups.
Other languages have mechanisms, such as packages in Ada and structures in Standard ML, that combine this with the additional purpose of allowing some names to be visible only to other members of their group.
For example, the following code produces a dialog with output undefined, as the local variable declaration is hoisted, shadowing the global variable, but the initialization is not, so the variable is undefined when used: Further, as functions are first-class objects in JavaScript and are frequently assigned as callbacks or returned from functions, when a function is executed, the name resolution depends on where it was originally defined (the lexical context of the definition), not the lexical context or execution context where it is called.
This code raises an error: The default name resolution rules can be overridden with the global or nonlocal (in Python 3) keywords.