Scope modifiers

From Rosetta Code
Revision as of 21:43, 17 June 2009 by rosettacode>Tinku99 (+ AutoHotkey)
Task
Scope modifiers
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

<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>

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.

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 it. //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>


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.

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.

Works with: Tcl version 8.5

<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.

Works with: Tcl version 8.6

<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.