In
programming language
A programming language is a system of notation for writing computer programs.
Programming languages are described in terms of their Syntax (programming languages), syntax (form) and semantics (computer science), semantics (meaning), usually def ...
s, name resolution is the resolution of the
tokens within program expressions to the intended program components.
Overview
Expressions in computer programs reference variables, data types, functions, classes, objects, libraries, packages and other entities by name. In that context, name resolution refers to the association of those not-necessarily-unique names with the intended program entities. The
algorithm
In mathematics and computer science, an algorithm () is a finite sequence of Rigour#Mathematics, mathematically rigorous instructions, typically used to solve a class of specific Computational problem, problems or to perform a computation. Algo ...
s that determine what those identifiers refer to in specific contexts are part of the language definition.
The complexity of these algorithms is influenced by the sophistication of the language. For example, name resolution in
assembly language
In computing, assembly language (alternatively assembler language or symbolic machine code), often referred to simply as assembly and commonly abbreviated as ASM or asm, is any low-level programming language with a very strong correspondence bet ...
usually involves only a single simple
table lookup, while name resolution in
C++ is extremely complicated as it involves:
*
namespace
In computing, a namespace is a set of signs (''names'') that are used to identify and refer to objects of various kinds. A namespace ensures that all of a given set of objects have unique names so that they can be easily identified.
Namespaces ...
s, which make it possible for an identifier to have different meanings depending on its associated namespace;
*
scopes, which make it possible for an identifier to have different meanings at different scope levels, and which involves various scope overriding and hiding rules. At the most basic level name resolution usually attempts to find the
binding in the smallest enclosing scope, so that for example local variables supersede global variables; this is called ''
shadowing''.
* ''visibility rules'', which determine whether identifiers from specific namespaces or scopes are visible from the current context;
*
overloading, which makes it possible for an identifier to have different meanings depending on how it is used, even in a single namespace or scope;
* ''accessibility'', which determines whether identifiers from an otherwise visible scope are actually accessible and participate in the name resolution process.
Static versus dynamic
In
programming language
A programming language is a system of notation for writing computer programs.
Programming languages are described in terms of their Syntax (programming languages), syntax (form) and semantics (computer science), semantics (meaning), usually def ...
s, name resolution can be performed either at
compile time or at
runtime. The former is called static name resolution, the latter is called dynamic name resolution.
A somewhat common misconception is that
dynamic typing implies dynamic name resolution. For example,
Erlang is dynamically typed but has static name resolution. However, static typing does imply static name resolution.
Static name resolution catches, at compile time, use of variables that are not in scope; preventing programmer errors. Languages with dynamic scope resolution sacrifice this safety for more flexibility; they can typically set and get variables in the same scope at runtime.
For example, in the
Python interactive
REPL:
>>> number = 99
>>> first_noun = "problems"
>>> second_noun = "hound"
>>> # Which variables to use are decided at runtime
>>> print(f"I got but a ain't one.")
I got 99 problems but a hound ain't one.
However, relying on dynamic name resolution in code is discouraged by the Python community. The feature also may be removed in a later version of Python.
Examples of languages that use static name resolution include
C,
C++,
E,
Erlang,
Haskell
Haskell () is a general-purpose, statically typed, purely functional programming language with type inference and lazy evaluation. Designed for teaching, research, and industrial applications, Haskell pioneered several programming language ...
,
Java
Java is one of the Greater Sunda Islands in Indonesia. It is bordered by the Indian Ocean to the south and the Java Sea (a part of Pacific Ocean) to the north. With a population of 156.9 million people (including Madura) in mid 2024, proje ...
,
Pascal,
Scheme, and
Smalltalk
Smalltalk is a purely object oriented programming language (OOP) that was originally created in the 1970s for educational use, specifically for constructionist learning, but later found use in business. It was created at Xerox PARC by Learni ...
. Examples of languages that use dynamic name resolution include some
Lisp
Lisp (historically LISP, an abbreviation of "list processing") is a family of programming languages with a long history and a distinctive, fully parenthesized Polish notation#Explanation, prefix notation.
Originally specified in the late 1950s, ...
dialects,
Perl
Perl is a high-level, general-purpose, interpreted, dynamic programming language. Though Perl is not officially an acronym, there are various backronyms in use, including "Practical Extraction and Reporting Language".
Perl was developed ...
,
PHP,
Python,
Rebol, and
Tcl.
Name masking
Masking occurs when the same identifier is used for different entities in overlapping lexical scopes. At the level of variables (rather than names), this is known as
variable shadowing. An identifier I' (for variable X') masks an identifier I (for variable X) when two conditions are met
# I' has the same name as I
# I' is defined in a scope which is a subset of the scope of I
The outer variable X is said to be ''shadowed'' by the inner variable X'.
For example, the parameter "foo" shadows the local variable "foo" in this common pattern:
private int foo; // Name "foo" is declared in the outer scope
public void setFoo(int foo)
public int getFoo()
Name masking can cause
complications in function overloading, due to overloading not happening across scopes in some languages, notably C++, thus requiring all overloaded functions to be redeclared or explicitly imported into a given namespace.
Alpha renaming to make name resolution trivial
In programming languages with
lexical scoping that do not
reflect over variable names,
α-conversion (or α-renaming) can be used to make name resolution easy by finding a substitution that makes sure that no variable name
masks another name in a containing scope. Alpha-renaming can make
static code analysis easier since only the alpha renamer needs to understand the language's scoping rules.
For example, in this code:
class Point
within the constructor, the
instance variables and are
shadowed by local variables of the same name. This might be alpha-renamed to:
class Point
In the new version, there is no masking, so it is immediately obvious which uses correspond to which declarations.
See also
*
Namespace (programming)
*
Scope (programming)
*
Naming collision
References
{{DEFAULTSORT:Name resolution
Computer libraries
Compiler construction