Scope modifiers: Difference between revisions
m fixing tags |
m →Variables: corrected requirements |
||
Line 474: | Line 474: | ||
Objects have an extra variable access mode. All the variables declared in a class definition are visible by default in the methods defined in that class. All other variable access modes are still available too. |
Objects have an extra variable access mode. All the variables declared in a class definition are visible by default in the methods defined in that class. All other variable access modes are still available too. |
||
{{works with|Tcl|8.6}} |
{{works with|Tcl|8.6}} or {{libheader|TclOO}} |
||
<lang tcl>oo::class create example { |
<lang tcl>oo::class create example { |
||
# Note that this is otherwise syntactically the same as a local variable |
# Note that this is otherwise syntactically the same as a local variable |
||
Line 486: | Line 486: | ||
} |
} |
||
[example new] showOff</lang>Output:<pre>variable objVar holds "This is an object variable"</pre> |
[example new] showOff</lang>Output:<pre>variable objVar holds "This is an object variable"</pre> |
||
===Commands=== |
===Commands=== |
||
Tcl commands are strictly always scoped to a particular namespace (defaulting to the global namespace, which is just a normal namespace in a somewhat privileged position). Commands are looked up in the current namespace first, then according to the current namespace's path rules (always empty prior to Tcl 8.5), and then finally in the global namespace. This effectively puts the global namespace in the scope of every namespace (though override-able in every namespace as well). By convention, library packages are placed in namespaces other than the global one (except for legacy cases or a single package access command) so that they don't cause unexpected conflicts; typically the global namespace is reserved for the Tcl language and user applications. |
Tcl commands are strictly always scoped to a particular namespace (defaulting to the global namespace, which is just a normal namespace in a somewhat privileged position). Commands are looked up in the current namespace first, then according to the current namespace's path rules (always empty prior to Tcl 8.5), and then finally in the global namespace. This effectively puts the global namespace in the scope of every namespace (though override-able in every namespace as well). By convention, library packages are placed in namespaces other than the global one (except for legacy cases or a single package access command) so that they don't cause unexpected conflicts; typically the global namespace is reserved for the Tcl language and user applications. |
Revision as of 12:04, 25 August 2010
You are encouraged to solve this task according to the task description, using any language you may know.
Most programming languages offer support for subroutines. When execution changes between subroutines, different sets of variables and functions ("scopes") are available to the program. Frequently these sets are defined by the placement of the variable and function declarations ("static scoping" or "lexical scoping"). These sets may also be defined by special modifiers to the variable and function declarations.
Show the different scope modifiers available in your language and briefly explain how they change the scope of their variable or function. If your language has no scope modifiers, note it.
Ada
Public and private declarative parts
In Ada declarative region of a package has publicly visible and private parts. The private part is introduced by private: <lang ada>package P is
... -- Declarations placed here are publicly visible
private
... -- These declarations are visible only to the children of P
end P;</lang> Correspondingly a type or object declaration may be incomplete in the public part providing an official interface. For example: <lang ada>package P is
type T is private; -- No components visible procedure F (X : in out T); -- The only visible operation N : constant T; -- A constant, which value is hidden
private
type T is record -- The implementation, visible to children only Component : Integer; end record; procedure V (X : in out T); -- Operation used only by children N : constant T := (Component => 0); -- Constant implementation
end P;</lang>
Bodies (invisible declarations)
The keyword body applied to the packages, protected objects and tasks. It specifies an implementation of the corresponding entity invisible from anywhere else: <lang ada>package body P is
-- The implementation of P, invisible to anybody procedure W (X : in out T); -- Operation used only internally
end P;</lang>
Private children
The keyword private can be applied to the whole package, a child of another package: <lang ada>private package P.Q is
... -- Visible to the siblings only
private
... -- Visible to the children only
end P.Q;</lang> This package can be then used only by private siblings of the same parent P.
AutoHotkey
Search autohotkey.com: modifiers
<lang AutoHotkey>singleton = "global variable"
assume_global() {
Global ; assume all variables declared in this function are global in scope Static callcount := 0 ; except this one declared static, initialized once only MsgBox % singleton ; usefull to initialize a bunch of singletons callcount++
}
assume_global2() {
Local var1 ; assume global except for var1 (similar to global scope declaration) MsgBox % singleton
}
object(member, value = 0, null = 0) {
Static ; assume all variables in this function to be static If value ; can be used to simulate objects
_%member% := value
Else If null
_%member% := ""
Return (_%member%)
}</lang>
C
The only scope modifier in C is static. The keyword static can make a global variable local to the file where it is declared (it has file scope); but it has a different meaning used inside functions or blocks. The extern keyword allows to access a "global" variable defined somewhere else.
file1.c <lang c>int a; // a is global static int p; // p is "locale" and can be seen only from file1.c
extern float v; // a global declared somewhere else
// a "global" function int code(int arg) {
int myp; // this can be seen only from inside code static int myc; // still a variable that can be seen only from // inside code, but it's value will be kept // among different code calls: it is not about // changing scope in this case!
}
// a "local" function; can be seen only inside file1.c static void code2(void) {
v = v * 1.02; // update global v // ...
}</lang>
file2.c <lang c>float v; // a global to be used from file1.c too static int p; // a file-scoped p; nothing to share with static p
// in file1.c
int code(int); // this is enough to be able to use global code defined in file1.c
// normally these things go into a header.h
// ...</lang>
Common Lisp
Common Lisp has exactly one scope modifier, the special
declaration, which causes occurrences of a variable within the scope of the declaration to have dynamic scope ("special variables") rather than lexical scope.
The defining operators defvar
and defparameter
globally declare a variable special, though this can also be done using declaim
. Local special declarations are rarely used. [This task should be expanded with some examples.]
E
E has no scope modifiers; all variables (including function definitions) are lexical. When more than one file is involved, all import/export of definitions is handled by explicit return values, parameters, or reified environments.
Haskell
Haskell has no scope modifiers; all variables are lexically scoped.
Site of declaration | Scope |
---|---|
Top level | The current module |
where construct
|
The definition to which the where is attached
|
let or case expression or lambda
|
The entire expression |
<- or let in a do block
|
All statements in the do block after the declaration
|
Icon and Unicon
Icon and Unicon data types are not declared and variables can take on any value; however, variables can be declared as to their scope. For more see un-Declarations it's all about scope.
Icon
<lang Icon>global var1 # used outside of procedures
procedure one() # a global procedure (the only kind) local var2 # used inside of procedures static var3 # also used inside of procedures end</lang>
Unicon
This Icon solution works in Unicon. Additionally Unicon supports classes with methods.
J
J's scoping rules are dynamic scope, limited to behave as lexical scope.
First approximation: All variables are either "global" in scope, or are local to the currently executing explicit definition. Local names shadow global names. J provides kinds of assignment -- assignment to a local name (=.) and assignment to a global name (=:). Shadowed global names can not be assigned to (because this is typically a programming mistake and can be easily avoided by performing the assignment in a different execution context). Here's an interactive session:
<lang J> A=: 1
B=: 2 C=: 3 F=: verb define A=:4 B=.5 D=.6 A+B+C+D ) F
18
A
4
B
2
D
|value error</lang>
Second approximation: J does not really have a global namespace. Instead, each object and each class has its own namespace. By default, interactive use updates the namespace for the class named 'base'. Further discussion of this issue is beyond the scope of this page.
Java
<lang java>public //any class may access this member directly
protected //only this class, subclasses of this class, //and classes in the same package may access this member directly
private //only this class may access this member directly
static //for use with other modifiers //limits this member to one reference for the entire JVM
//adding no modifier allows access to the member by classes in the same package
//method parameters are available inside the entire method
//Other declarations follow lexical scoping, //being in the scope of the innermost set of braces ({}) to them. //You may also create local scopes by surrounding blocks of code with braces.
public void function(int x){
//can use x here int y; //can use x and y here { int z; //can use x, y, and z here } //can use x and y here, but NOT z
}</lang>
Logo
Traditional Logo has dynamic scope for all symbols except for parameters, ostensibly so that it is easy to inspect bound values in an educational setting. UCB Logo also has a LOCAL syntax for declaring a dynamically scoped variable visible to a procedure and those procedures it calls. <lang logo> make "g 5 ; global
to proc :p
make "h 4 ; also global local "l ; local, no initial value localmake "m 3
sub 7
end
to sub :s
; can see :g, :h, and :s ; if called from proc, can also see :l and :m localmake "h 5 ; hides global :h within this procedure and those it calls
end </lang>
MUMPS
MUMPS variable can be in a local scope if they are declared as NEW within a subroutine. Otherwise variables are accessible to all levels. <lang MUMPS>OUTER
SET OUT=1,IN=0 WRITE "OUT = ",OUT,! WRITE "IN = ",IN,! DO INNER WRITE:$DATA(OUT)=0 "OUT was destroyed",! QUIT
INNER
WRITE "OUT (inner scope) = ",OUT,! WRITE "IN (outer scope) = ",IN,! NEW IN SET IN=3.14 WRITE "IN (inner scope) = ",IN,! KILL OUT QUIT</lang>
Execution:
USER>D ^SCOPE OUT = 1 IN = 0 OUT (inner scope) = 1 IN (outer scope) = 0 IN (inner scope) = 3.14 OUT was destroyed
Perl
A name explicitly qualified as belonging to a package with ::
(like $Foo::bar
; as a special case, for any identifier var
and sigil $
, $::var
is short for $main::var
) always refers to a package variable, i.e., a global variable belonging to the given package. So only unqualified names can have context-sensitive interpretations.
By default, an unqualified name refers to a package variable in the current package. The current package is whatever you set it to with the last package
declaration in the current lexical scope, or main
by default. But wherever stricture is in effect, using a name that would be resolved this way is a compile-time error.
There are three kinds of declaration that can influence the scoping of a particular variable: our
, my
, and local
. our
makes a package variable lexically available. Its primary use is to allow easy access to package variables under stricture.
<lang perl>use strict; $x = 1; # Compilation error. our $y = 2; print "$y\n"; # Legal; refers to $main::y.
package Foo; our $z = 3; package Bar; print "$z\n"; # Refers to $Foo::z.</lang>
my
creates a new lexical variable, independent of any package. It's destroyed as soon as it falls out of scope, and each execution of the statement containing the my
creates a new, independent variable.
<lang perl>package Foo; my $fruit = 'apple'; package Bar; print "$fruit\n"; # Prints "apple". {
my $fruit = 'banana'; print "$fruit\n"; # Prints "banana".
} print "$fruit\n"; # Prints "apple".
# The second $fruit has been destroyed.
our $fruit = 'orange'; print "$fruit\n"; # Prints "orange"; refers to $Bar::fruit.
# The first $fruit is inaccessible.</lang>
local
gives a package variable a new value for the duration of the current dynamic scope.
<lang perl>our $camelid = 'llama';
sub phooey {
print "$camelid\n";
}
phooey; # Prints "llama".
sub do_phooey {
local $camelid = 'alpaca'; phooey;
}
do_phooey; # Prints "alpaca". phooey; # Prints "llama".</lang>
Usually, my
is preferrable to local
, but one thing local
can do that my
can't is affect the special punctuation variables, like $/
and $"
. Actually, in perl 5.9.1 and later, my $_
is specially allowed and works as you would expect.
PicoLisp
PicoLisp distinguishes between "scope" and "binding". The scope of a symbol determines its visibility in a given context (whether or not it can be accessed), while binding is about assigning it a value.
Scope
In PicoLisp, the scope type of a symbol is either "internal", "transient" or "external". It is specified lexically: Internal symbols are just normal symbols. Transient symbols are surrounded by double quotes (and thus look like strings in other languages), and/or with an underlined font if possible. External symbols are surrounded by braces.
- The scope of an internal symbol is global. This means that a symbol like AB123 is always the same object, residing at a certain location in memory (pointer equality).
- A transient symbol like "AB123" is the same only within the current transient scope. This is normally a single source file, but may be further subdivided. Within that scope it can be used like an internal symbol, but after the transient scope is closed it cannot be accessed by its name any longer. This behavior is similar to "static" identifiers in the C language.
- External symbols like {AB123} are persistent database symbols. They have a permanent identity among different processes and over time. Besides that, they have the same structure like internal and transient symbols: A value, properties and a name.
Binding
Regardless of the scope, the binding of symbols to values is always dynamic. This happens implicitly for function parameters, or explicitly with functions like let, use, bind, job and others. This means that the current value of a symbol is saved locally, then set to the new value. When done, the old value is restored. Closures are created by maintaining an explicit environment. More about that here.
PowerShell
Variables can have a specific scope, which is one of global, local, script, private. Variables with the same name can exist in different scopes and are shadowed by child scopes. The scope of a variable can be directly prefixed to the variable name: <lang powershell>$a = "foo" # global scope function test {
$a = "bar" # local scope Write-Host Local: $a # "bar" - local variable Write-Host Global: $global:a # "foo" - global variable
}</lang> The various cmdlets dealing with variables also have a –Scope parameter, enabling one to specify a relative or absolute scope for the variable to be manipulated.
PureBasic
- Functions must be defined before being used and are always global in scope.
- Variables must be defined before being used. They do not have to be explicity defined, simply using them will define them. The keyword EnableExplicit may also be used to require explicit definitions before using a variable.
- Two main divisions in scope exist. The first scope is the body of code outside of all procedures and the second is the scope within a single given procedure.
- If a variable is not explicitly defined its scope is local to one of the aforementioned areas. This may be modified by using one of the keywords: Global, Protected, or Shared. The effects are detailed by the comments in the sample code.
<lang PureBasic>;define a local integer variable by simply using it baseAge.i = 10
- explicitly define local strings
Define person.s = "Amy", friend.s = "Susan"
- define variables that are both accessible inside and outside procedures
Global ageDiff = 3 Global extraYears = 5
Procedure test()
;define a local integer variable by simply using it baseAge.i = 30 ;explicitly define a local string Define person.s = "Bob" ;allow access to a local variable in the main body of code Shared friend ;create a local variable distinct from a variable with global scope having the same name Protected extraYears = 2 PrintN(person + " and " + friend + " are " + Str(baseAge) + " and " + Str(baseAge + ageDiff + extraYears) + " years old.")
EndProcedure
If OpenConsole()
test() PrintN(person + " and " + friend + " are " + Str(baseAge) + " and " + Str(baseAge + ageDiff + extraYears) + " years old.") Print(#CRLF$ + #CRLF$ + "Press ENTER to exit") Input() CloseConsole()
EndIf</lang> Code output:
Bob and Susan are 30 and 35 years old. Amy and Susan are 10 and 18 years old.
Python
Python from version 3 has the global and nonlocal access modifiers:
global
instructs the interpreter to search for the name(s) in the outermost sccope.nonlocal
instructs the interpreter to search for the name(s) starting from the innermost enclosing scope going outwards.
Without either keyword, a reference to a name must have the name defined in the current scope or if not, then it is looked for in the global scope - skipping any intermediate scopes.
In the example below the name x
is defined at various scopes and given a different value dependent on its scope. The innermost functions demonstrate how the scope modifiers give acccess to the name from different scopes:
<lang python>>>> x="From global scope" >>> def outerfunc():
x = "From scope at outerfunc"
def scoped_local(): x = "scope local" return "scoped_local scope gives x = " + x print(scoped_local())
def scoped_nonlocal(): nonlocal x return "scoped_nonlocal scope gives x = " + x print(scoped_nonlocal())
def scoped_global(): global x return "scoped_global scope gives x = " + x print(scoped_global())
def scoped_notdefinedlocally(): return "scoped_notdefinedlocally scope gives x = " + x print(scoped_notdefinedlocally())
>>> outerfunc()
scoped_local scope gives x = scope local
scoped_nonlocal scope gives x = From scope at outerfunc
scoped_global scope gives x = From global scope
scoped_notdefinedlocally scope gives x = From global scope
>>></lang>
More information on the scope modifiers can be found here.
R
R uses lexical scoping – there is a nice introduction to this in the FAQ on R. There are no keywords related to scoping, but the assign function allows you to choose the environment in which a variable is assigned. The global assignment operators , '<<-' and '->>' are effectively shorthand for 'assign(..., envir=globalenv()). <lang r>x <- "defined in global env" foo <- function() {
# Print existing value print(x) # "defined in global env" # define a local value and print it x <- "defined inside foo" print(x) # "defined inside foo" # remove local value, reassign global value from within foo rm(x) assign("x", "reassigned global value", envir=globalenv()) print(x) # "reassigned global value"
} foo()</lang>
Tcl
Variables
In Tcl procedures, variables are local to the procedure unless explicitly declared otherwise (unless they contain namespace separators, which forces interpretation as namespace-scoped names). Declarations may be used to access variables in the global namespace, or the current namespace, or indeed any other namespace.
<lang tcl>set globalVar "This is a global variable" namespace eval nsA {
variable varInA "This is a variable in nsA"
} namespace eval nsB {
variable varInB "This is a variable in nsB" proc showOff {varname} { set localVar "This is a local variable" global globalVar variable varInB namespace upvar ::nsA varInA varInA puts "variable $varname holds \"[set $varname]\"" }
} nsB::showOff globalVar nsB::showOff varInA nsB::showOff varInB nsB::showOff localVar</lang> Output:
variable globalVar holds "This is a global variable" variable varInA holds "This is a variable in nsA" variable varInB holds "This is a variable in nsB" variable localVar holds "This is a local variable"
Objects have an extra variable access mode. All the variables declared in a class definition are visible by default in the methods defined in that class. All other variable access modes are still available too.
or
<lang tcl>oo::class create example {
# Note that this is otherwise syntactically the same as a local variable variable objVar constructor {} { set objVar "This is an object variable" } method showOff {} { puts "variable objVar holds \"$objVar\"" }
}
[example new] showOff</lang>Output:
variable objVar holds "This is an object variable"
Commands
Tcl commands are strictly always scoped to a particular namespace (defaulting to the global namespace, which is just a normal namespace in a somewhat privileged position). Commands are looked up in the current namespace first, then according to the current namespace's path rules (always empty prior to Tcl 8.5), and then finally in the global namespace. This effectively puts the global namespace in the scope of every namespace (though override-able in every namespace as well). By convention, library packages are placed in namespaces other than the global one (except for legacy cases or a single package access command) so that they don't cause unexpected conflicts; typically the global namespace is reserved for the Tcl language and user applications.
General Caller Scope Access
Of considerable relevance to this area are the upvar
and uplevel
commands. The first allows a variable name to be resolved to a variable in the scope of a caller of the current procedure and linked to a local variable in the current stack frame, and the second allows the execution of arbitrary code in the context of a caller of the current procedure. Both can work with any stack frame on the call stack (which consequently becomes a call tree) but the two most commonly referred-to frames are the immediate caller of the current procedure and the global/topmost stack frame.
To demonstrate these capabilities, here is an example of how we can create a decr
command that is just like the incr
command except for working with increments in the opposite direction.
<lang tcl>proc decr {varName {decrement 1}} {
upvar 1 $varName var incr var [expr {-$decrement}]
}</lang>
Here is a kind of version of eval
that concatenates its arguments with a semicolon first, instead of the default behavior (a space):
<lang tcl>proc semival args {
uplevel 1 [join $args ";"]
}</lang> Of course, these capabilities are designed to be used together. Here is a command that will run a loop over a variable between two bounds, executing a "block" for each step. <lang tcl>proc loop {varName from to body} {
upvar 1 $varName var for {set var $from} {$var <= $to} {incr var} { uplevel 1 $body }
}
loop x 1 10 {
puts "x is now $x" if {$x == 5} { puts "breaking out..." break }
} puts "done"</lang> which prints:
x is now 1 x is now 2 x is now 3 x is now 4 x is now 5 breaking out... done
As you can see, these are very powerful capabilities which make it trivial to write control structures in next to no Tcl code at all.
TI-89 BASIC
The only scope modifier in TI-89 BASIC is the Local
command, which makes the variable local to the enclosing program or function rather than global (in some folder).
<lang ti89b>Local x 2 → x Return x^x</lang>
Ursala
There are no variables in Ursala except dummy variables used in lambda abstractions, but scope rules govern the visibility of constants and function declarations.
When compiling a library, directives such as #library
and #binary
can
be switched on and off throughout a source text, and only the symbols
declared when they're on will become visible library entry points.
<lang Ursala>local_shop = 0
hidden_variable = 3
- library+
this_public_constant = local_shop a_visible_function = +
- library-
for_local_people = 7</lang>
By default, every symbol is visible to every other within the same
file, and multiple declarations of the same symbol are an error, but the
scope modifiers #hide
and #export
can create multiple
scopes within a single file. In this example, the symbol x
will have
a value of 1,
<lang Ursala>foo = 1
- hide+
foo = 2 bar = 3
- hide-
x = foo</lang>
but it will be 2 in this example, where
the #export
directive selectively allows an otherwise
hidden declaration to be visible outside its enclosing
scope, and allows name clashes to be resolved by proximity.
<lang Ursala>foo = 1
- hide+
- export+
foo = 2
- export-
bar = 3
- hide-
x = foo</lang>
The #hide
directives can be arbitrarily nested in matched pairs
to create block structured scope, but doing so is likely to be
overkill.
When name clashes occur between imported and locally declared symbols, they are resolved by default in favor of the local declaration. However, this behavior can be overridden using the dash operator as shown. <lang Ursala>#import std
cat = 3
a_string = std-cat('foo','bar')</lang>
Here, std-cat
refers to the concatenation function from the standard
library, not the locally declared constant by that name.