Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Scope (computer science)
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== By language == {{expand section|date=April 2013}} Scope rules for representative languages follow. === C === {{main article|Linkage (software)}} In C, scope is traditionally known as '''[[Linkage (software)|linkage]]''' or '''visibility''', particularly for variables. C is a lexically scoped language with global scope (known as ''external linkage''), a form of module scope or file scope (known as ''internal linkage''), and local scope (within a function); within a function scopes can further be nested via block scope. However, standard C does not support nested functions. The lifetime and visibility of a variable are determined by its [[storage class]]. There are three types of lifetimes in C: static (program execution), automatic (block execution, allocated on the stack), and manual (allocated on the heap). Only static and automatic are supported for variables and handled by the compiler, while manually allocated memory must be tracked manually across different variables. There are three levels of visibility in C: external linkage (global), internal linkage (roughly file), and block scope (which includes functions); block scopes can be nested, and different levels of internal linkage is possible by use of includes. Internal linkage in C is visibility at the [[Translation unit (programming)|translation unit]] level, namely a source file after being processed by the [[C preprocessor]], notably including all relevant includes. C programs are compiled as separate [[object file]]s, which are then linked into an executable or library via a [[Linker (computing)|linker]]. Thus name resolution is split across the compiler, which resolves names within a translation unit (more loosely, "compilation unit", but this is properly a different concept), and the linker, which resolves names across translation units; see [[Linkage (software)|linkage]] for further discussion. In C, variables with block scope enter context when they are declared (not at the top of the block), go out of context if any (non-nested) function is called within the block, come back into context when the function returns, and go out of context at the end of the block. In the case of automatic local variables, they are also allocated on declaration and deallocated at the end of the block, while for static local variables, they are allocated at program initialization and deallocated at program termination. The following program demonstrates a variable with block scope coming into context partway through the block, then exiting context (and in fact being deallocated) when the block ends: <syntaxhighlight lang="c"> #include <stdio.h> int main(void) { char x = 'm'; printf("%c\n", x); { printf("%c\n", x); char x = 'b'; printf("%c\n", x); } printf("%c\n", x); } </syntaxhighlight> The program outputs: <pre> m m b m </pre> There are other levels of scope in C.<ref>"[http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fzexscope_c.htm Scope]", ''XL C/C++ V8.0 for Linux,'' IBM</ref> Variable names used in a function prototype have function prototype visibility, and exit context at the end of the function prototype. Since the name is not used, this is not useful for compilation, but may be useful for documentation. Label names for GOTO statement have function scope. === C++ === All the variables that we intend to use in a program must have been declared with its type specifier in an earlier point in the code, like we did in the previous code at the beginning of the body of the function main when we declared that a, b, and result were of type int. A variable can be either of global or local scope. A global variable is a variable declared in the main body of the source code, outside all functions, while a local variable is one declared within the body of a function or a block. Modern versions [[Anonymous function#C++ (since C++11)|allow]] nested lexical scope. === Swift === [[Swift (programming language)|Swift]] has a similar rule for scopes with C++, but contains different access modifiers. {| class="wikitable" |- ! Modifier !! Immediate scope !! File !! Containing module/package !! Rest of the world |- | open || {{yes}} || {{yes}} || {{yes}} || {{Yes}}, allows subclass |- | public || {{yes}} || {{yes}} || {{yes}} || {{yes}}, disallows subclass |- | internal || {{yes}} || {{yes}} || {{yes}} || {{no}} |- | fileprivate || {{yes}} || {{yes}} || {{no}} || {{no}} |- | private || {{yes}} || {{no}} || {{no}} || {{no}} |} === Go === [[Go (programming language)|Go]] is lexically scoped using blocks.<ref name=go/> === Java === [[Java (programming language)|Java]] is lexically scoped. A Java class has several kinds of variables:<ref>{{cite web|url=https://docs.oracle.com/javase/tutorial/java/javaOO/variables.html|title=Declaring Member Variables (The Java Tutorials > Learning the Java Language > Classes and Objects)|website=docs.oracle.com|access-date=19 March 2018}}</ref> ; Local variables: are defined inside a method, or a particular block. These variables are local to where they were defined and lower levels. For example, a loop inside a method can use that method's local variables, but not the other way around. The loop's variables (local to that loop) are destroyed as soon as the loop ends. ; Member variables: also called ''fields'' are variables declared within the class, outside of any method. By default, these variables are available for all methods within that class and also for all classes in the package. ; Parameters: are variables in method declarations. In general, a set of brackets defines a particular scope, but variables at top level within a class can differ in their behavior depending on the modifier keywords used in their definition. The following table shows the access to members permitted by each modifier.<ref>{{cite web|url=https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html|title=Controlling Access to Members of a Class (The Java Tutorials > Learning the Java Language > Classes and Objects)|website=docs.oracle.com|access-date=19 March 2018}}</ref> {| class="wikitable" |- ! Modifier !! Class !! Package !! Subclass !! World |- | public || {{yes}} || {{yes}} || {{yes}} || {{Yes}} |- | protected || {{yes}} || {{yes}} || {{yes}} || {{no}} |- | (no modifier) || {{yes}} || {{yes}} || {{no}} || {{no}} |- | private || {{yes}} || {{no}} || {{no}} || {{no}} |} === JavaScript === [[JavaScript]] has simple ''scope rules'',<ref>"[http://www.coolcoder.in/2014/03/everything-you-need-to-know-about.html Everything you need to know about Javascript variable scope]", [http://www.coolcoder.in/p/about-us.html Saurab Parakh], ''[http://www.coolcoder.in/ Coding is Cool],'' 2010-02-08</ref> but variable initialization and name resolution rules can cause problems, and the widespread use of closures for callbacks means the lexical context of a function when defined (which is used for name resolution) can be very different from the lexical context when it is called (which is irrelevant for name resolution). JavaScript objects have name resolution for properties, but this is a separate topic. JavaScript has lexical scope <ref>{{cite web|url=https://es5.github.io/#x10.2|title=Annotated ES5|website=es5.github.io|access-date=19 March 2018}}</ref> nested at the function level, with the global context being the outermost context. This scope is used for both variables and for functions (meaning function declarations, as opposed to variables of [[function type]]).<ref>{{cite web|url=https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope|title=Functions|website=MDN Web Docs|access-date=19 March 2018}}</ref> Block scope with the <code>let</code> and <code>[[const (computer programming)|const]]</code> keywords is standard since [[ECMAScript]] 6. Block scope can be produced by wrapping the entire block in a function and then executing it; this is known as the [[immediately-invoked function expression]] (IIFE) pattern. While JavaScript scope is simple—lexical, function-level—the associated initialization and name resolution rules are a cause of confusion. Firstly, assignment to a name not in scope defaults to creating a new global variable, not a local one. Secondly, to create a new local variable one must use the <code>var</code> keyword; the variable is then created at the top of the function, with value <code>undefined</code> and the variable is assigned its value when the assignment expression is reached: :A variable with an ''Initialiser'' is assigned the value of its ''AssignmentExpression'' when the ''VariableStatement'' is executed, not when the variable is created.<ref>"[https://es5.github.io/#x12.2 12.2 Variable Statement]", Annotated ECMAScript 5.1, Last updated: 2012-05-28</ref> This is known as ''[[variable hoisting]]''<ref>"[http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html JavaScript Scoping and Hoisting]", [http://www.adequatelygood.com/about.html Ben Cherry], ''[http://www.adequatelygood.com/ Adequately Good],'' 2010-02-08</ref>—the declaration, but not the initialization, is hoisted to the top of the function. Thirdly, accessing variables before initialization yields <code>undefined</code>, rather than a syntax error. Fourthly, for function declarations, the declaration and the initialization are both hoisted to the top of the function, unlike for variable initialization. For example, the following code produces a dialog with output <samp>undefined</samp>, as the local variable declaration is hoisted, shadowing the global variable, but the initialization is not, so the variable is undefined when used: <syntaxhighlight lang="javascript"> a = 1; function f() { alert(a); var a = 2; } f(); </syntaxhighlight> 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. The nested scopes of a particular function (from most global to most local) in JavaScript, particularly of a closure, used as a callback, are sometimes referred to as the '''scope chain''', by analogy with the prototype chain of an object. [[Closure (computer science)|Closures]] can be produced in JavaScript by using nested functions, as functions are first-class objects.<ref>[http://jibbering.com/faq/notes/closures/ Javascript Closures], Richard Cornford. March 2004</ref> Returning a nested function from an enclosing function includes the local variables of the enclosing function as the (non-local) lexical context of the returned function, yielding a closure. For example: <syntaxhighlight lang="javascript"> function newCounter() { // return a counter that is incremented on call (starting at 0) // and which returns its new value var a = 0; var b = function() { a++; return a; }; return b; } c = newCounter(); alert(c() + ' ' + c()); // outputs "1 2" </syntaxhighlight> Closures are frequently used in JavaScript, due to being used for callbacks. Indeed, any hooking of a function in the local context as a callback or returning it from a function creates a closure if there are any unbound variables in the function body (with the context of the closure based on the nested scopes of the current lexical context, or "scope chain"); this may be accidental. When creating a callback based on parameters, the parameters must be stored in a closure, otherwise it will accidentally create a closure that refers to the variables in the enclosing context, which may change.<ref> "[http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/ Explaining JavaScript Scope And Closures]", Robert Nyman, October 9, 2008</ref> Name resolution of properties of JavaScript objects is based on inheritance in the prototype tree—a path to the root in the tree is called a ''prototype chain''—and is separate from name resolution of variables and functions. === Lisp === [[Lisp (programming language)|Lisp]] dialects have various rules for scope. The original Lisp used dynamic scope; it was [[Scheme (programming language)|Scheme]], inspired by [[ALGOL]], that introduced static (lexical) scope to the Lisp family. [[Maclisp]] used dynamic scope by default in the interpreter and lexical scope by default in compiled code, though compiled code could access dynamic bindings by use of <code>SPECIAL</code> declarations for particular variables.<ref>{{cite web |url=http://maclisp.info/pitmanual/complr.html#23.1.2 |title=The Revised Maclisp Manual (The Pitmanual), Sunday Morning Edition |last=Pitman |first=Kent |date=December 16, 2007 |website=MACLISP.info |publisher=HyperMeta Inc. |access-date=October 20, 2018|at=Declarations and the Compiler, Concept "Variables" |quote= If the variable to be bound has been declared to be special, the binding is compiled as code to imitate the way the interpreter binds variables }}</ref> However, [[Maclisp]] treated lexical binding more as an optimization than one would expect in modern languages, and it did not come with the [[Closure (computer programming)|closure]] feature one might expect of lexical scope in modern Lisps. A separate operation, <code>*FUNCTION</code>, was available to somewhat clumsily work around some of that issue.<ref>{{cite web |url=http://www.maclisp.info/pitmanual/eval.html#3.7.1 |title=The Revised Maclisp Manual (The Pitmanual), Sunday Morning Edition |last=Pitman |first=Kent |date=December 16, 2007 |website=MACLISP.info |publisher=HyperMeta Inc. |access-date=October 20, 2018|at=The Evaluator, Special Form <code>*FUNCTION</code> |quote= <code>*FUNCTION</code> is intended to help solve the "[[funarg problem]]," however it only works in some easy cases. }}</ref> [[Common Lisp]] adopted lexical scope from [[Scheme (programming language)|Scheme]],<ref>{{cite web |url=http://www.lispworks.com/documentation/lw50/CLHS/Body/01_ab.htm |title=Common Lisp HyperSpec |last=Pitman |first=Kent |collaboration=webbed version of ANSI standard X3.226-1994 |date=1996 |website=Lispworks.com |publisher=LispWorks Ltd. |access-date=October 20, 2018|at=1.1.2 History |quote=MacLisp improved on the Lisp 1.5 notion of special variables ... The primary influences on Common Lisp were Lisp Machine Lisp, MacLisp, NIL, S-1 Lisp, Spice Lisp, and Scheme. }}</ref> as did [[Clojure]]. [[ISLISP]] has lexical scope for ordinary variables. It also has dynamic variables, but they are in all cases explicitly marked; they must be defined by a <code>defdynamic</code> special form, bound by a <code>dynamic-let</code> special form, and accessed by an explicit <code>dynamic</code> special form.<ref>{{cite web |url=http://www.islisp.info/Documents/PDF/islisp-2007-03-17-pd-v23.pdf |title=Programming Language ISLISP, ISLISP Working Draft 23.0|website=ISLISP.info |access-date=October 20, 2018 |at=11.1 The lexical principle |quote= Dynamic bindings are established and accessed by a separate mechanism (i.e., <code>defdynamic</code>, <code>dynamic-let</code>, and <code>dynamic</code>).}}</ref> Some other dialects of Lisp, like [[Emacs Lisp]], still use dynamic scope by default. Emacs Lisp now has lexical scope available on a per-buffer basis.<ref name=":0">{{cite web |url=https://www.emacswiki.org/emacs/LexicalBinding |title=Lexical Binding |website=EmacsWiki |access-date=October 20, 2018 |quote=Emacs 24 has optional lexical binding, which can be enabled on a per-buffer basis. }}</ref> === Python === For variables, Python has function scope, module scope, and global scope. Names enter context at the start of a scope (function, module, or global scope), and exit context when a non-nested function is called or the scope ends. If a name is used prior to variable initialization, this raises a runtime exception. If a variable is simply accessed (not assigned to), name resolution follows the LEGB (Local, Enclosing, Global, Built-in) rule which resolves names to the narrowest relevant context. However, if a variable is assigned to, it defaults to declaring a variable whose scope starts at the start of the level (function, module, or global), not at the assignment. Both these rules can be overridden with a <code>global</code> or <code>nonlocal</code> (in Python 3) declaration prior to use, which allows accessing global variables even if there is a masking nonlocal variable, and assigning to global or nonlocal variables. As a simple example, a function resolves a variable to the global scope: <syntaxhighlight lang="pycon"> >>> def f(): ... print(x) ... >>> x = "global" >>> f() global </syntaxhighlight> Note that <code>x</code> is defined before <code>f</code> is called, so no error is raised, even though it is defined after its reference in the definition of <code>f</code>. Lexically this is a [[forward reference]], which is allowed in Python. Here assignment creates a new local variable, which does not change the value of the global variable: <syntaxhighlight lang="pycon"> >>> def f(): ... x = "f" ... print(x) ... >>> x = "global" >>> print(x) global >>> f() f >>> print(x) global </syntaxhighlight> Assignment to a variable within a function causes it to be declared local to the function, hence its scope is the entire function, and thus using it prior to this assignment raises an error. This differs from C, where the scope of the local variable start at its declaration. This code raises an error: <syntaxhighlight lang="pycon"> >>> def f(): ... print(x) ... x = "f" ... >>> x = "global" >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f UnboundLocalError: local variable 'x' referenced before assignment </syntaxhighlight> The default name resolution rules can be overridden with the <code>global</code> or <code>nonlocal</code> (in Python 3) keywords. In the below code, the <code>global x</code> declaration in <code>g</code> means that <code>x</code> resolves to the global variable. It thus can be accessed (as it has already been defined), and assignment assigns to the global variable, rather than declaring a new local variable. Note that no <code>global</code> declaration is needed in <code>f</code>—since it does not assign to the variable, it defaults to resolving to the global variable. <syntaxhighlight lang="pycon"> >>> def f(): ... print(x) ... >>> def g(): ... global x ... print(x) ... x = "g" ... >>> x = "global" >>> f() global >>> g() global >>> f() g </syntaxhighlight> <code>global</code> can also be used for nested functions. In addition to allowing assignment to a global variable, as in an unnested function, this can also be used to access the global variable in the presence of a nonlocal variable: <syntaxhighlight lang="pycon"> >>> def f(): ... def g(): ... global x ... print(x) ... x = "f" ... g() ... >>> x = "global" >>> f() global </syntaxhighlight> For nested functions, there is also the <code>nonlocal</code> declaration, for assigning to a nonlocal variable, similar to using <code>global</code> in an unnested function: <syntaxhighlight lang="pycon"> >>> def f(): ... def g(): ... nonlocal x # Python 3 only ... x = "g" ... x = "f" ... g() ... print(x) ... >>> x = "global" >>> f() g >>> print(x) global </syntaxhighlight> === R === [[R (programming language)|R]] is a lexically scoped language, unlike other implementations of [[S (programming language)|S]] where the values of free variables are determined by a set of global variables, while in R they are determined by the context in which the function was created.<ref>{{cite web|url=https://cran.r-project.org/doc/FAQ/R-FAQ.html#Lexical-scoping|title=R FAQ|website=cran.r-project.org|access-date=19 March 2018}}</ref> The scope contexts may be accessed using a variety of features (such as <code>parent.frame()</code>) which can simulate the experience of dynamic scope should the programmer desire. There is no block scope: <syntaxhighlight lang="r"> a <- 1 { a <- 2 } message(a) ## 2 </syntaxhighlight> Functions have access to scope they were created in: <syntaxhighlight lang="r"> a <- 1 f <- function() { message(a) } f() ## 1 </syntaxhighlight> Variables created or modified within a function stay there: <syntaxhighlight lang="r"> a <- 1 f <- function() { message(a) a <- 2 message(a) } f() ## 1 ## 2 message(a) ## 1 </syntaxhighlight> Variables created or modified within a function stay there unless assignment to enclosing scope is explicitly requested: <syntaxhighlight lang="r"> a <- 1 f <- function() { message(a) a <<- 2 message(a) } f() ## 1 ## 2 message(a) ## 2 </syntaxhighlight> Although R has lexical scope by default, function scopes can be changed: <syntaxhighlight lang="r"> a <- 1 f <- function() { message(a) } my_env <- new.env() my_env$a <- 2 f() ## 1 environment(f) <- my_env f() ## 2 </syntaxhighlight>
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)