Scope/Function names and labels: Difference between revisions
m (→{{header|Phix}}: phix/basics) |
m (→{{header|Wren}}: Minor tidy) |
||
(8 intermediate revisions by 8 users not shown) | |||
Line 9: | Line 9: | ||
* [[Scope modifiers]] for general scope modification facilities |
* [[Scope modifiers]] for general scope modification facilities |
||
<br><br> |
<br><br> |
||
=={{header|6502 Assembly}}== |
|||
6502 Assembly has no scope rules by default. The entire address space of the CPU is a valid target for the <code>JMP</code> command. The enforcement of scope is up to the assembler itself, which can allow the programmer to define local labels. Prior to conversion into an address, each local label with the same name is padded with a unique sequence of numbers not shown to the programmer, to fulfill the assembler's requirement that all code labels are unique. Assemblers that don't have local label features require that no label be used in more than one place. |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
Algol 68 follows the traditional block structure scoping rules introduced by Algol 60. |
Algol 68 follows the traditional block structure scoping rules introduced by Algol 60. |
||
Line 18: | Line 19: | ||
In addition, functions etc. declared between IF and THEN are in scope in the THEN and ELSE parts, but |
In addition, functions etc. declared between IF and THEN are in scope in the THEN and ELSE parts, but |
||
declarations in the THEN part and not visible in the ELSE part (and vice versa), so the following is invalid: |
declarations in the THEN part and not visible in the ELSE part (and vice versa), so the following is invalid: |
||
< |
<syntaxhighlight lang="algol68">IF PROC x = ...; |
||
... |
... |
||
THEN |
THEN |
||
Line 29: | Line 30: | ||
... |
... |
||
l1: ... |
l1: ... |
||
FI</ |
FI</syntaxhighlight> |
||
Similarly, declarations between WHILE and DO are in scope between DO and OD and those declared between CASE and IN are visible in the IN and OUT parts of a CASE. |
Similarly, declarations between WHILE and DO are in scope between DO and OD and those declared between CASE and IN are visible in the IN and OUT parts of a CASE. |
||
<br> |
<br> |
||
Line 40: | Line 41: | ||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
In awk, function names are always global and can be referenced in sections of code appearing before the definition: |
In awk, function names are always global and can be referenced in sections of code appearing before the definition: |
||
< |
<syntaxhighlight lang="awk"># This program outputs a greeting |
||
BEGIN { |
BEGIN { |
||
sayhello() # Call the function defined below |
sayhello() # Call the function defined below |
||
Line 48: | Line 49: | ||
function sayhello { |
function sayhello { |
||
print "Hello World!" # Outputs a message to the terminal |
print "Hello World!" # Outputs a message to the terminal |
||
}</ |
}</syntaxhighlight> |
||
Note that the awk extraction and reporting language is data driven and does not support arbitary line labels. |
Note that the awk extraction and reporting language is data driven and does not support arbitary line labels. |
||
Line 56: | Line 57: | ||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
Line numbers are used instead of labels. These are also immediately accessible as soon as the line is entered, even if the program is not run: |
Line numbers are used instead of labels. These are also immediately accessible as soon as the line is entered, even if the program is not run: |
||
< |
<syntaxhighlight lang="basic">GOTO 50: REM THIS WILL WORK IMMEDIATELY</syntaxhighlight> |
||
The visibility of functions depends on the implementation. Most versions of basic will allow a function to be referenced from a point in the code prior to its definition. However, other implementations may require the function definition to be run, before it can be used: |
The visibility of functions depends on the implementation. Most versions of basic will allow a function to be referenced from a point in the code prior to its definition. However, other implementations may require the function definition to be run, before it can be used: |
||
< |
<syntaxhighlight lang="basic">10 DEF FN S(A)=A*A |
||
20 PRINT FN S(2): REM THIS WILL WORK |
20 PRINT FN S(2): REM THIS WILL WORK |
||
30 PRINT FN C(2): REM CALLING A FUNCTION PRIOR TO DEFINITION MAY NOT WORK |
30 PRINT FN C(2): REM CALLING A FUNCTION PRIOR TO DEFINITION MAY NOT WORK |
||
Line 65: | Line 66: | ||
60 END |
60 END |
||
9000 DEF FN C(A)=A*A*A |
9000 DEF FN C(A)=A*A*A |
||
9999 RETURN</ |
9999 RETURN</syntaxhighlight> |
||
=={{header|bc}}== |
=={{header|bc}}== |
||
Line 74: | Line 75: | ||
There are no labels in bc. |
There are no labels in bc. |
||
< |
<syntaxhighlight lang="bc">f(1) /* First output line */ |
||
define f(x) { |
define f(x) { |
||
return(x) |
return(x) |
||
Line 83: | Line 84: | ||
return(x - 1) |
return(x - 1) |
||
} |
} |
||
f(3) /* Third output line */</ |
f(3) /* Third output line */</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
Line 93: | Line 94: | ||
Demonstrating function scope as well as goto in a C program invariably leads to code like the one below. The [http://en.wikipedia.org/wiki/Scope_(computer_science)#C Wikipedia article] is a good starting point. |
Demonstrating function scope as well as goto in a C program invariably leads to code like the one below. The [http://en.wikipedia.org/wiki/Scope_(computer_science)#C Wikipedia article] is a good starting point. |
||
<syntaxhighlight lang="c"> |
|||
<lang C> |
|||
#include <stdio.h> |
#include <stdio.h> |
||
Line 144: | Line 145: | ||
printf("If you are trying to figure out what happened, you now understand goto.\n"); |
printf("If you are trying to figure out what happened, you now understand goto.\n"); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} Example run: |
{{out}} Example run: |
||
Line 160: | Line 161: | ||
If you are trying to figure out what happened, you now understand goto. |
If you are trying to figure out what happened, you now understand goto. |
||
</pre> |
</pre> |
||
=={{header|Delphi}}== |
|||
{{works with|Delphi|6.0}} |
|||
{{libheader|SysUtils,StdCtrls}} |
|||
1. Delphi is a one pass compiler, so the names of procedures, functions, variables, constants and types are only visible to code that comes after the item was declared. Procedure and functions can be "Forward" declared, which allows them to be declared before they are defined. |
|||
2. All items inside an object are visible throughout the object, no matter the order they are defined. Outside an object, the object and items inside it are only visible to code that comes after it was declared. |
|||
3. Delphi prodedures and functions can be nested. Varibles inside a procedure or function are only visible from inside the same procedures or functions. Variable, procedures and functions at higher levels of nesting are visible to lower levels of nesting. |
|||
4. Items inside objects have controlled visibility to the outside world. Objects are divided in specific sections that control the visibility of items inside the section. Here is a list of sections: |
|||
Private: Items contained within the "Private" section of an object are only visible inside the object. |
|||
Protected: Item contained within the "Protected" section of an object are only visible inside the object or inside object that inherit from the object. |
|||
Public: Item contained within the "Public" section of an object are completely visible to the outside world. |
|||
Published: Item contained within the "Published" section of an object are visible to the outside world and can be manipulated by the IDE. |
|||
<syntaxhighlight lang="Delphi"> |
|||
// Test1 is visible to Test2, but not vice versa. |
|||
// The local variables A, B, and C invisible to the outside world. |
|||
procedure Test1; |
|||
var A,B,C: integer; |
|||
begin |
|||
end; |
|||
procedure Test2; |
|||
var A,B,C: integer; |
|||
begin |
|||
end; |
|||
// Test1 is visible to all code that follows it. |
|||
// Test2 is invisible to the ouside world |
|||
procedure Test1; |
|||
var A,B,C: integer; |
|||
procedure Test2; |
|||
var A,B,C: integer; |
|||
begin |
|||
end; |
|||
begin |
|||
end; |
|||
// Item1 and Test1 are only visible inside the object |
|||
// Item2 and Test2 are additional to inhered objects |
|||
// Item3 and Test3 are visible to the outside world |
|||
// Item4 is visible to the outside world and the IDE |
|||
type TMyObject = class(TObject) |
|||
private |
|||
Item1: integer |
|||
procedure Test1; |
|||
protected |
|||
Item2: integer |
|||
procedure Test2; |
|||
public |
|||
Item3: integer |
|||
procedure Test3; |
|||
published |
|||
property Item4: integer read FItem4 write FItem4; |
|||
end; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
</pre> |
|||
=={{header|Eiffel}}== |
=={{header|Eiffel}}== |
||
Line 166: | Line 247: | ||
All features are assigned (at compile-time) to a particular scope defined by the most-recently preceding feature clause. Various feature clauses are given below, from least restrictive (most visible) to most restrictive (most hidden). |
All features are assigned (at compile-time) to a particular scope defined by the most-recently preceding feature clause. Various feature clauses are given below, from least restrictive (most visible) to most restrictive (most hidden). |
||
< |
<syntaxhighlight lang="eiffel">--assume A, B and C to be valid classes |
||
class X |
class X |
||
feature -- alias for "feature {ANY}" |
feature -- alias for "feature {ANY}" |
||
Line 186: | Line 267: | ||
-- features following this clause are only visible to this particular instance of X |
-- features following this clause are only visible to this particular instance of X |
||
end</ |
end</syntaxhighlight> |
||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
Line 193: | Line 274: | ||
There are no labels. |
There are no labels. |
||
<syntaxhighlight lang="erlang"> |
|||
<lang Erlang> |
|||
-module( a_module ). |
-module( a_module ). |
||
Line 201: | Line 282: | ||
local_function() -> 2. |
local_function() -> 2. |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
Each word belongs to a vocabulary. Vocabularies may be added to the vocabulary search path to put their words in scope. For example, to use the <code>+</code> word: |
Each word belongs to a vocabulary. Vocabularies may be added to the vocabulary search path to put their words in scope. For example, to use the <code>+</code> word: |
||
< |
<syntaxhighlight lang="factor">USE: math |
||
2 2 +</ |
2 2 +</syntaxhighlight> |
||
Words are visible in the vocabulary where they are defined. But only after the point where they have been defined. |
Words are visible in the vocabulary where they are defined. But only after the point where they have been defined. |
||
< |
<syntaxhighlight lang="factor">USE: io |
||
IN: hello-vocab |
IN: hello-vocab |
||
hello ! error; hello hasn't been defined yet |
hello ! error; hello hasn't been defined yet |
||
: hello ( -- ) "Hello, world!" print ; |
: hello ( -- ) "Hello, world!" print ; |
||
hello ! visible here</ |
hello ! visible here</syntaxhighlight> |
||
This restriction can be lifted through the use of <code>DEFER:</code>. |
This restriction can be lifted through the use of <code>DEFER:</code>. |
||
< |
<syntaxhighlight lang="factor">USE: io |
||
IN: hello-vocab |
IN: hello-vocab |
||
Line 224: | Line 305: | ||
hello ! visible here |
hello ! visible here |
||
: hello ( -- ) "Hello, world!" print ; |
: hello ( -- ) "Hello, world!" print ; |
||
hello ! visible here</ |
hello ! visible here</syntaxhighlight> |
||
=={{header|FreeBASIC}}== |
|||
'''PROCEDURES''' |
|||
A <code>'''function'''</code> defines a block of code which can be executed with a single statement (a function call), and provide a value back to the caller when finished (a return value): |
|||
There are several reasons to use functions |
|||
* Reduces redundancy in your program. |
|||
* Enables reuse of code in many programs. |
|||
* Improves readability of the program. |
|||
* Improves maintainability of the program. |
|||
* Makes it easy to extend your program. |
|||
A <code>'''subroutine'''</code> is a block of code which may be called at any time from a program. |
|||
This code may need to be executed multiple times, and subroutines provide an invaluable means to simplify code by replacing these blocks of code with a single subroutine call. |
|||
A subroutine also serves to allow a user to extend the FreeBASIC language to provide custom commands. |
|||
Many of the functions built into FreeBASIC are merely subroutines part of a "runtime library" linked to by default. |
|||
Scope (visibility) of a procedure through the different modules of a program. |
|||
A procedure is a '''subroutine''' (sub) or a '''function''' that can be called by code outside the procedure (or internal code in the case of a recursion). |
|||
A procedure consists of a sequence of instructions that form the body of the procedure. |
|||
It is possible to pass values or variables to a procedure, and a function may return a value or a reference. |
|||
Scopes of procedures in modules follows simple rules: |
|||
# '''Private scope''': procedure visible only in its own module (where it is defined). |
|||
# '''Public scope''': procedure visible from all modules constituting a compiled program (including static libraries). |
|||
# '''Export scope''': when defined in a DLL (dynamically linked library), procedure visible from an external program that has loaded it (statically or dynamically). |
|||
'''LABELS''' |
|||
A <code>'''label'''</code> defines a place in a program where Goto or GoSub can jump to. |
|||
A label can be a positive integer line number or a symbolname. In both cases, the label must start at the first column of line. A symbolname label must end with a colon (:) character. |
|||
Is available only in the "-lang qb" and "-lang fblite" dialect. |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Line 235: | Line 351: | ||
A function definition, either a top-level declaration or a function literal, represents a function block. |
A function definition, either a top-level declaration or a function literal, represents a function block. |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 258: | Line 374: | ||
// ex.x() non-exported function not visible here |
// ex.x() non-exported function not visible here |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="go">package ex |
||
import ( |
import ( |
||
Line 275: | Line 391: | ||
func x() { // not exported, x not upper case. |
func x() { // not exported, x not upper case. |
||
panic("top level x") |
panic("top level x") |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 283: | Line 399: | ||
Labels can only be declared in function blocks. The scope is the function block where the label is declared excluding any nested function blocks. |
Labels can only be declared in function blocks. The scope is the function block where the label is declared excluding any nested function blocks. |
||
< |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 311: | Line 427: | ||
} |
} |
||
// end: // labels not allowed outside function blocks</ |
// end: // labels not allowed outside function blocks</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 320: | Line 436: | ||
Functions are considered global in haskell and can be referenced in the sections of code appearing before the function definition. The following code illustrates the same. add2 was declared after add3 and used in add3. The variables x,y and z are local to the function. |
Functions are considered global in haskell and can be referenced in the sections of code appearing before the function definition. The following code illustrates the same. add2 was declared after add3 and used in add3. The variables x,y and z are local to the function. |
||
< |
<syntaxhighlight lang="haskell"> |
||
add3 :: Int -> Int-> Int-> Int |
add3 :: Int -> Int-> Int-> Int |
||
add3 x y z = add2 x y + z |
add3 x y z = add2 x y + z |
||
Line 328: | Line 444: | ||
main :: putStrLn(show (add3 5 6 5)) |
main :: putStrLn(show (add3 5 6 5)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Output}} |
{{Output}} |
||
<pre> |
<pre> |
||
Line 337: | Line 453: | ||
In the function below the functions g and h are local to the function getSquaredSum. They cannot be called from anywhere outside the function. |
In the function below the functions g and h are local to the function getSquaredSum. They cannot be called from anywhere outside the function. |
||
< |
<syntaxhighlight lang="haskell"> |
||
getSquaredSum :: Int-> Int-> Int |
getSquaredSum :: Int-> Int-> Int |
||
getSquaredSum x y = g x + h y |
getSquaredSum x y = g x + h y |
||
Line 343: | Line 459: | ||
g a = a*a |
g a = a*a |
||
h b = b*b |
h b = b*b |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Output}} |
{{Output}} |
||
<pre> |
<pre> |
||
Line 371: | Line 487: | ||
'''Local''' scope, names defined using =. will have local scope if a block scope exists. |
'''Local''' scope, names defined using =. will have local scope if a block scope exists. |
||
< |
<syntaxhighlight lang="j"> a=. 1</syntaxhighlight> |
||
'''Locale''' scope, names defined using =: will have locale scope (and the '''base''' locale is used by default). |
'''Locale''' scope, names defined using =: will have locale scope (and the '''base''' locale is used by default). |
||
< |
<syntaxhighlight lang="j"> b=: 2</syntaxhighlight> |
||
Names may include a locale qualifier. A locative is a qualified name. Locale qualifiers contain two '''_''' characters, are a suffix on what would be the unqualified name. Locale qualifiers come in two forms: absolute and relative. Relative locale qualifiers use another name in the current locale to identify the target locale. Absolute locatives place the locale name between the two '''_''' characters, while relative locatives name the locale reference following the pair of '''_''' characters. |
Names may include a locale qualifier. A locative is a qualified name. Locale qualifiers contain two '''_''' characters, are a suffix on what would be the unqualified name. Locale qualifiers come in two forms: absolute and relative. Relative locale qualifiers use another name in the current locale to identify the target locale. Absolute locatives place the locale name between the two '''_''' characters, while relative locatives name the locale reference following the pair of '''_''' characters. |
||
< |
<syntaxhighlight lang="j"> c_thingy_=: 3 |
||
d=: <'test' |
d=: <'test' |
||
e__d=: 4 |
e__d=: 4 |
||
b + e_test_ |
b + e_test_ |
||
6</ |
6</syntaxhighlight> |
||
If a local definition exists for a name, it is an error to use use =: to assign that name (use a locative instead of the unqualified name if you really need to do this). |
If a local definition exists for a name, it is an error to use use =: to assign that name (use a locative instead of the unqualified name if you really need to do this). |
||
< |
<syntaxhighlight lang="j">verb define '' |
||
f=. 6 |
f=. 6 |
||
g=: 7 |
g=: 7 |
||
Line 394: | Line 510: | ||
) |
) |
||
|domain error |
|domain error |
||
| g =:9</ |
| g =:9</syntaxhighlight> |
||
Meanwhile, there is a global current locale (default: '''base''') but each verb's definition is evaluated with the current locale being the locale where that verb was defined. |
Meanwhile, there is a global current locale (default: '''base''') but each verb's definition is evaluated with the current locale being the locale where that verb was defined. |
||
Line 408: | Line 524: | ||
Labels are available in explicit definitions, and are names beginning with '''label_''' and ending with a '''.'''. You may use them with a goto which is a name beginning with '''goto_''' and ending with a '''.'''. Use of labels is restricted to the scope where they are defined, and they cannot be used to enter control structures (except in the sense of the normal entry point). |
Labels are available in explicit definitions, and are names beginning with '''label_''' and ending with a '''.'''. You may use them with a goto which is a name beginning with '''goto_''' and ending with a '''.'''. Use of labels is restricted to the scope where they are defined, and they cannot be used to enter control structures (except in the sense of the normal entry point). |
||
< |
<syntaxhighlight lang="j">example=:3 :0 |
||
if. y do. |
if. y do. |
||
echo 0 |
echo 0 |
||
Line 427: | Line 543: | ||
example 0 |
example 0 |
||
2 |
2 |
||
5</ |
5</syntaxhighlight> |
||
=={{header|jq}}== |
=={{header|jq}}== |
||
Line 446: | Line 562: | ||
A similar rule applies to two inner functions defined within the same enclosing function. Otherwise, inner functions of the same |
A similar rule applies to two inner functions defined within the same enclosing function. Otherwise, inner functions of the same |
||
name can co-exist. In particular, a function named NAME may define an inner function of the same name. For example: |
name can co-exist. In particular, a function named NAME may define an inner function of the same name. For example: |
||
< |
<syntaxhighlight lang="jq">def NAME: |
||
def NAME: 2; |
def NAME: 2; |
||
1, NAME; # this calls the inner function, not the outer function |
1, NAME; # this calls the inner function, not the outer function |
||
NAME # => 1, 2</ |
NAME # => 1, 2</syntaxhighlight> |
||
'''Mutually Defined Functions''' |
'''Mutually Defined Functions''' |
||
The "declare-before-use" rule means that two top-level functions cannot be defined in terms of each other. Consider the following example: |
The "declare-before-use" rule means that two top-level functions cannot be defined in terms of each other. Consider the following example: |
||
< |
<syntaxhighlight lang="jq">def F(x): if x == 0 then M(x) else 1 end; # NOT POSSIBLE |
||
def M(x): if x == 1 then F(x) else 2 end;</ |
def M(x): if x == 1 then F(x) else 2 end;</syntaxhighlight> |
||
There are several possible workarounds using inner functions. For example, if both F and M must be top-level functions, we could define them as follows: |
There are several possible workarounds using inner functions. For example, if both F and M must be top-level functions, we could define them as follows: |
||
< |
<syntaxhighlight lang="jq">def F(x): |
||
def M(x): if x == 1 then F(x) else 2 end; |
def M(x): if x == 1 then F(x) else 2 end; |
||
if x == 0 then M(x) else 1 end; |
if x == 0 then M(x) else 1 end; |
||
def M(x): if x == 1 then F(x) else 2 end;</ |
def M(x): if x == 1 then F(x) else 2 end;</syntaxhighlight> |
||
If F and M are not required to be top-level functions, then both F and M could be defined as inner functions of the same enclosing function. |
If F and M are not required to be top-level functions, then both F and M could be defined as inner functions of the same enclosing function. |
||
Line 516: | Line 632: | ||
The following program illustrates some of these usages. |
The following program illustrates some of these usages. |
||
< |
<syntaxhighlight lang="scala">// version 1.1.2 |
||
// top level function visible anywhere within the current module |
// top level function visible anywhere within the current module |
||
Line 581: | Line 697: | ||
l() // invokes lambda |
l() // invokes lambda |
||
println("Good-bye!") // will be executed |
println("Good-bye!") // will be executed |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 600: | Line 716: | ||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
In Lua, variables are global by default, but can be modified to be local to the block in which they are declared. |
In Lua, variables are global by default, but can be modified to be local to the block in which they are declared. |
||
< |
<syntaxhighlight lang="lua">function foo() print("global") end -- global scope by default |
||
foo() |
foo() |
||
local function foo() print("local module") end -- local to the current block (which is the module) |
local function foo() print("local module") end -- local to the current block (which is the module) |
||
Line 619: | Line 735: | ||
end -- close the block (and thus its scope) |
end -- close the block (and thus its scope) |
||
foo() -- module-level local still exists |
foo() -- module-level local still exists |
||
_G.foo() -- global still exists</ |
_G.foo() -- global still exists</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>global |
<pre>global |
||
Line 645: | Line 761: | ||
There are statements Goto and Gosub as in Basic, including On Goto and On Gosub. We can make simple routines using Return to return from them.We can jump out from a block of code. We can't do the opposite, to enter in a block of code from outside. We can't jump out of Module or Function block, we can exit only using Exit or Break statements (Break exit on multiple blocks, Exit exit the current block). So Goto used to exit from a specific inner block to some block above it. |
There are statements Goto and Gosub as in Basic, including On Goto and On Gosub. We can make simple routines using Return to return from them.We can jump out from a block of code. We can't do the opposite, to enter in a block of code from outside. We can't jump out of Module or Function block, we can exit only using Exit or Break statements (Break exit on multiple blocks, Exit exit the current block). So Goto used to exit from a specific inner block to some block above it. |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Function Master { |
Function Master { |
||
Module Alfa { |
Module Alfa { |
||
Line 705: | Line 821: | ||
\\ No variables exist after the return from Master() |
\\ No variables exist after the return from Master() |
||
Print Valid(M)=False |
Print Valid(M)=False |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Nim}}== |
|||
In Nim, procedures can be defined at the module level, which is the most frequent, or in any other scope, for instance in another procedure or even in a loop or an if statement. That means that, as regards scoping, procedures are managed as variables, types, etc. |
|||
When defined at the module level, a procedure is considered private to the module. To make it visible from other modules (provided they import the whole module or only the procedure), the procedure must be annotated with an “*”. |
|||
Labels are only used when defining a block which opens a new scope: <code>block outer:</code>. This label is only used to allow breaking from the block (useful when we want to exit from internal loops): <code>break outer</code>. The label is only visible in the block. |
|||
Note that blocks are allowed anywhere where code is allowed, and so are labels. This is perfectly valid: |
|||
<syntaxhighlight lang="nim"> const C = block useless: 3</syntaxhighlight> |
|||
=={{header|Objeck}}== |
|||
In Objeck function, names may be public or private. Access to the classes that contain functions can be explicit or controlled at the file level by "use" statements. |
|||
=={{header|Oforth}}== |
=={{header|Oforth}}== |
||
Line 713: | Line 843: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
Perl allows various ways to futz with scope, but keeping it simple: Routines are package-scoped, and in each package the final definition of the routine is the one that is used throughout. Labels are generally also package-scoped, except when it comes to <code>goto</code>; let's don't even go there. |
Perl allows various ways to futz with scope, but keeping it simple: Routines are package-scoped, and in each package the final definition of the routine is the one that is used throughout. Labels are generally also package-scoped, except when it comes to <code>goto</code>; let's don't even go there. |
||
< |
<syntaxhighlight lang="perl">no warnings 'redefine'; |
||
sub logger { print shift . ": Dicitur clamantis in deserto." }; # discarded |
sub logger { print shift . ": Dicitur clamantis in deserto." }; # discarded |
||
Line 735: | Line 865: | ||
sub logger { |
sub logger { |
||
print shift . ": This thought intentionally left blank.\n" # routine for 'main' package |
print shift . ": This thought intentionally left blank.\n" # routine for 'main' package |
||
};</ |
};</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>A: This thought intentionally left blank. |
<pre>A: This thought intentionally left blank. |
||
Line 751: | Line 881: | ||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
<syntaxhighlight lang="pl/i"> |
|||
<lang PL/I> |
|||
Functions are normally internal to a program. If they are at the nesting level |
Functions are normally internal to a program. If they are at the nesting level |
||
immediately within the program, they are accessible from anywhere in the program. |
immediately within the program, they are accessible from anywhere in the program. |
||
Line 759: | Line 889: | ||
Functions can be compiled separately, and then linked with a program |
Functions can be compiled separately, and then linked with a program |
||
in which case they are globally accessible. |
in which case they are globally accessible. |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|PowerShell}}== |
=={{header|PowerShell}}== |
||
Line 767: | Line 897: | ||
You can specify the scope of a function. For example, the function is added to the global scope in the following example: |
You can specify the scope of a function. For example, the function is added to the global scope in the following example: |
||
<syntaxhighlight lang="powershell"> |
|||
<lang PowerShell> |
|||
function global:Get-DependentService |
function global:Get-DependentService |
||
{ |
{ |
||
Get-Service | Where-Object {$_.DependentServices} |
Get-Service | Where-Object {$_.DependentServices} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
When a function is in the global scope, you can use the function in scripts, in functions, and at the command line. |
When a function is in the global scope, you can use the function in scripts, in functions, and at the command line. |
||
Line 778: | Line 908: | ||
For more information about scope in Windows PowerShell, see about_Scopes |
For more information about scope in Windows PowerShell, see about_Scopes |
||
<syntaxhighlight lang="powershell"> |
|||
<lang PowerShell> |
|||
Get-Help about_Scopes |
Get-Help about_Scopes |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
Line 797: | Line 927: | ||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Racket inherits the strict lexical-scopedness of Scheme, so function bindings (like any other bindings) are visible only within their scope. For example |
Racket inherits the strict lexical-scopedness of Scheme, so function bindings (like any other bindings) are visible only within their scope. For example |
||
< |
<syntaxhighlight lang="racket"> |
||
(define (foo x) |
(define (foo x) |
||
(define (bar y) (+ x y)) |
(define (bar y) (+ x y)) |
||
Line 803: | Line 933: | ||
(foo 1) ; => 3 |
(foo 1) ; => 3 |
||
(bar 1) ; => error |
(bar 1) ; => error |
||
</syntaxhighlight> |
|||
</lang> |
|||
but that applies only to the *bindings* -- the actual function values (like other values) can be passed around freely: |
but that applies only to the *bindings* -- the actual function values (like other values) can be passed around freely: |
||
< |
<syntaxhighlight lang="racket"> |
||
(define (foo x) |
(define (foo x) |
||
(define (bar y) (+ x y)) |
(define (bar y) (+ x y)) |
||
Line 811: | Line 941: | ||
(foo 1) ; => #<procedure:bar> |
(foo 1) ; => #<procedure:bar> |
||
((foo 1) 2) ; => 3 |
((foo 1) 2) ; => 3 |
||
</syntaxhighlight> |
|||
</lang> |
|||
But it should be noted that Racket is flexible enough to make it possible to implement other kinds of scope. |
But it should be noted that Racket is flexible enough to make it possible to implement other kinds of scope. |
||
Line 837: | Line 967: | ||
</pre> |
</pre> |
||
<lang |
<syntaxhighlight lang="raku" line># call a routine before it has been defined |
||
say log(); # prints: outer |
say log(); # prints: outer |
||
Line 889: | Line 1,019: | ||
# call the original overridden CORE routine |
# call the original overridden CORE routine |
||
say &CORE::log(e); # prints: 1 ( natural log of e ) |
say &CORE::log(e); # prints: 1 ( natural log of e ) |
||
}</ |
}</syntaxhighlight> |
||
Labels are less interesting and are typically useful only for control flow in looping constructs. They generally follow the same scoping rules as "my" variables. There is nearly always easier ways to do control flow though, so they aren't heavily used. |
Labels are less interesting and are typically useful only for control flow in looping constructs. They generally follow the same scoping rules as "my" variables. There is nearly always easier ways to do control flow though, so they aren't heavily used. |
||
Line 916: | Line 1,046: | ||
::::: (optional blanks) |
::::: (optional blanks) |
||
::::::: ────(a repeat of the above as many times as is possible on a line of code)──── |
::::::: ────(a repeat of the above as many times as is possible on a line of code)──── |
||
< |
<syntaxhighlight lang="rexx">/*REXX program demonstrates the use of labels and also a CALL statement. */ |
||
blarney = -0 /*just a blarney & balderdash statement*/ |
blarney = -0 /*just a blarney & balderdash statement*/ |
||
signal do_add /*transfer program control to a label.*/ |
signal do_add /*transfer program control to a label.*/ |
||
Line 930: | Line 1,060: | ||
add.2.args: procedure; parse arg x,y; return x+y /*first come, first served ···*/ |
add.2.args: procedure; parse arg x,y; return x+y /*first come, first served ···*/ |
||
add.2.args: say 'Whoa Nelly!! Has the universe run amok?' /*didactic, but never executed*/ |
add.2.args: say 'Whoa Nelly!! Has the universe run amok?' /*didactic, but never executed*/ |
||
add.2.args: return arg(1) + arg(2) /*concise, " " " */</ |
add.2.args: return arg(1) + arg(2) /*concise, " " " */</syntaxhighlight> |
||
'''output''' |
'''output''' |
||
<pre> |
<pre> |
||
Line 938: | Line 1,068: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
# Project : Scope/Function names and labels |
# Project : Scope/Function names and labels |
||
Line 947: | Line 1,077: | ||
func welcome(name) |
func welcome(name) |
||
see "hello " + name + nl |
see "hello " + name + nl |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 957: | Line 1,087: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
'def' starts the definition of a method, and 'end' ends it - no cute little curly braces. |
'def' starts the definition of a method, and 'end' ends it - no cute little curly braces. |
||
< |
<syntaxhighlight lang="ruby"> |
||
def welcome(name) |
def welcome(name) |
||
puts "hello #{name}" |
puts "hello #{name}" |
||
Line 964: | Line 1,094: | ||
$name = STDIN.gets |
$name = STDIN.gets |
||
welcome($name) |
welcome($name) |
||
return </ |
return </syntaxhighlight> |
||
'''output''' |
'''output''' |
||
<pre> |
<pre> |
||
Line 973: | Line 1,103: | ||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
< |
<syntaxhighlight lang="scala">object ScopeFunction extends App { |
||
val c = new C() |
val c = new C() |
||
val d = new D() |
val d = new D() |
||
Line 1,027: | Line 1,157: | ||
println("Good-bye!") // will be executed |
println("Good-bye!") // will be executed |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
In Sidef, the same rule which is applied to variable scoping, is applied to functions and classes as well, which means that a function defined inside another function is not visible outside the current scope. |
In Sidef, the same rule which is applied to variable scoping, is applied to functions and classes as well, which means that a function defined inside another function is not visible outside the current scope. |
||
< |
<syntaxhighlight lang="ruby"># Nested functions |
||
func outer { |
func outer { |
||
func inner {}; # not visible outside |
func inner {}; # not visible outside |
||
Line 1,039: | Line 1,169: | ||
class Outer { |
class Outer { |
||
class Inner {}; # not visisble outside |
class Inner {}; # not visisble outside |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
There are a number of different symbol types in Tcl, all of which are handled independently. Each namespace contains a mapping from (simple) command names to command implementations; when a command is looked up, the search is done by looking in the current namespace, then in the namespaces on that namespace's path (which is usually empty), and finally in the global namespace. There are ''no'' local commands (unlike with variables, though a lambda expression in a variable can act very similarly to a command). Commands only have a mapping after they have been created; the <code>proc</code> “declaration” is just a command that creates a procedure at the point where it is called. |
There are a number of different symbol types in Tcl, all of which are handled independently. Each namespace contains a mapping from (simple) command names to command implementations; when a command is looked up, the search is done by looking in the current namespace, then in the namespaces on that namespace's path (which is usually empty), and finally in the global namespace. There are ''no'' local commands (unlike with variables, though a lambda expression in a variable can act very similarly to a command). Commands only have a mapping after they have been created; the <code>proc</code> “declaration” is just a command that creates a procedure at the point where it is called. |
||
< |
<syntaxhighlight lang="tcl">doFoo 1 2 3; # Will produce an error |
||
proc doFoo {a b c} { |
proc doFoo {a b c} { |
||
puts [expr {$a + $b*$c}] |
puts [expr {$a + $b*$c}] |
||
} |
} |
||
doFoo 1 2 3; # Will now print 7 (and will continue to do so until doFoo is renamed or deleted</ |
doFoo 1 2 3; # Will now print 7 (and will continue to do so until doFoo is renamed or deleted</syntaxhighlight> |
||
Tcl does not support labels, either outside or inside procedures. (Other mechanisms are used for jumps and state machines.) |
Tcl does not support labels, either outside or inside procedures. (Other mechanisms are used for jumps and state machines.) |
||
Line 1,055: | Line 1,185: | ||
There is no lookahead in the shell, so functions cannot be called until their definition has been run: |
There is no lookahead in the shell, so functions cannot be called until their definition has been run: |
||
< |
<syntaxhighlight lang="sh">#!/bin/sh |
||
multiply 3 4 # This will not work |
multiply 3 4 # This will not work |
||
echo $? # A bogus value was returned because multiply definition has not yet been run. |
echo $? # A bogus value was returned because multiply definition has not yet been run. |
||
Line 1,064: | Line 1,194: | ||
multiply 3 4 # Ok. It works now. |
multiply 3 4 # Ok. It works now. |
||
echo $? # This gives 12</ |
echo $? # This gives 12</syntaxhighlight> |
||
The shell does not support the use of arbitrary line labels. |
The shell does not support the use of arbitrary line labels. |
||
=={{header|V (Vlang)}}== |
|||
Vlang has both functions and labels. |
|||
A function definition, either a top level declaration or a function literal, represents a function block. |
|||
<syntaxhighlight lang="Vlang"> |
|||
fn world() { |
|||
print("World!") |
|||
} |
|||
fn main() { |
|||
// anonymous function |
|||
f := fn() { |
|||
print("Hello ") |
|||
} |
|||
f() // "Hello |
|||
world() // World!" |
|||
// "Hello World!" |
|||
} |
|||
</syntaxhighlight> |
|||
Functions can be used before their declaration (below main), but can still be called from main. |
|||
This eliminates the need for header files or worrying about the order. |
|||
<syntaxhighlight lang="Vlang"> |
|||
fn main() { |
|||
println(add(77, 33)) |
|||
println(sub(100, 50)) |
|||
} |
|||
fn add(x int, y int) int { |
|||
return x + y |
|||
} |
|||
fn sub(x int, y int) int { |
|||
return x - y |
|||
} |
|||
</syntaxhighlight> |
|||
Functions are private (not exported) by default. To allow other modules to use them, prepend pub |
|||
<syntaxhighlight lang="Vlang"> |
|||
pub fn public_function() { |
|||
} |
|||
fn private_function() { |
|||
} |
|||
</syntaxhighlight> |
|||
Labelled break & continue: |
|||
You can also use break and continue followed by a label name to refer to an outer for loop. |
|||
<syntaxhighlight lang="Vlang"> |
|||
outer: for i := 4; true; i++ { |
|||
println(i) |
|||
for { |
|||
if i < 7 { |
|||
continue outer |
|||
} else { |
|||
break outer |
|||
} |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
Goto and labels: |
|||
1) The label name must be contained within the same function as the 'goto' statement. |
|||
2) Used only with 'unsafe' statements. |
|||
<syntaxhighlight lang="Vlang"> |
|||
// Unsafe 'goto' pseudo example: |
|||
if x { |
|||
// ... |
|||
if y { |
|||
unsafe { |
|||
goto my_label |
|||
} |
|||
} |
|||
// ... |
|||
} |
|||
my_label: |
|||
</syntaxhighlight> |
|||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
Line 1,076: | Line 1,286: | ||
The following example illustrates these points. |
The following example illustrates these points. |
||
< |
<syntaxhighlight lang="wren">//func.call() /* invalid, can't call func before its declared */ |
||
var func = Fn.new { System.print("func has been called.") } |
var func = Fn.new { System.print("func has been called.") } |
||
Line 1,089: | Line 1,299: | ||
} |
} |
||
C.init() // fine</ |
C.init() // fine</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,098: | Line 1,308: | ||
(with line 1 uncommented) |
(with line 1 uncommented) |
||
[./ |
[./Scope_Function_names_and_labels line 3] Error at '}': Variable 'func' referenced before this definition (first use at line 1). |
||
(with only line 7 uncommented) |
(with only line 7 uncommented) |
||
func has been called. |
func has been called. |
||
Null does not implement 'init()'. |
Null does not implement 'init()'. |
||
[./ |
[./Scope_Function_names_and_labels line 7] in (script) |
||
</pre> |
</pre> |
||
Line 1,124: | Line 1,334: | ||
Functions have two modifiers, public (the default) and private. Private is the same as public inside the compilation unit, outside that unit/file, a private function can only be accessed via reflection. |
Functions have two modifiers, public (the default) and private. Private is the same as public inside the compilation unit, outside that unit/file, a private function can only be accessed via reflection. |
||
< |
<syntaxhighlight lang="zkl">class C{ fcn [private] f{} }</syntaxhighlight> |
||
=={{header|ZX Spectrum Basic}}== |
=={{header|ZX Spectrum Basic}}== |
||
Functions are visible as soon as they are entered, even if the program is not run. Line numbers are used instead of labels. These are also immediately accessible as soon as the line is entered, even if the program is not run: |
Functions are visible as soon as they are entered, even if the program is not run. Line numbers are used instead of labels. These are also immediately accessible as soon as the line is entered, even if the program is not run: |
||
< |
<syntaxhighlight lang="zxbasic">9000 REM The function is immediately visible and usable |
||
9010 DEF FN s(x)=x*x |
9010 DEF FN s(x)=x*x |
||
PRINT FN s(5): REM This will work immediately |
PRINT FN s(5): REM This will work immediately |
||
GO TO 50: REM This will work immediately</ |
GO TO 50: REM This will work immediately</syntaxhighlight> |
||
{{omit from|GUISS|does not have functions or labels}} |
{{omit from|GUISS|does not have functions or labels}} |
Revision as of 10:27, 4 February 2024
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Explain or demonstrate the levels of visibility of function names and labels within the language.
- See also
- Variables for levels of scope relating to visibility of program variables
- Scope modifiers for general scope modification facilities
6502 Assembly
6502 Assembly has no scope rules by default. The entire address space of the CPU is a valid target for the JMP
command. The enforcement of scope is up to the assembler itself, which can allow the programmer to define local labels. Prior to conversion into an address, each local label with the same name is padded with a unique sequence of numbers not shown to the programmer, to fulfill the assembler's requirement that all code labels are unique. Assemblers that don't have local label features require that no label be used in more than one place.
ALGOL 68
Algol 68 follows the traditional block structure scoping rules introduced by Algol 60.
A label, function (PROC), variable etc. declared in an outer block is only visible within that block and all inner blocks,
unless another label, function, etc. is declared with the same name in an inner block.
In addition, functions etc. declared between IF and THEN are in scope in the THEN and ELSE parts, but
declarations in the THEN part and not visible in the ELSE part (and vice versa), so the following is invalid:
IF PROC x = ...;
...
THEN
# can call x here #
PROC y = ...;
...
GO TO l1 # invalid!! #
ELSE
# can call x here, but not y #
...
l1: ...
FI
Similarly, declarations between WHILE and DO are in scope between DO and OD and those declared between CASE and IN are visible in the IN and OUT parts of a CASE.
Note that labels cannot be defined between IF and THEN, between WHILE and DO and between CASE and IN.
ALGOL W
Algol W follows the scoping rules of Algol 60 - a function (called a procedure) or a label is only in scope within the block it is declared in and in blocks nested within that block. If a procedure, label, variable etc. is declared with same name in an inner block, the outer definition is inaccessible.
AWK
In awk, function names are always global and can be referenced in sections of code appearing before the definition:
# This program outputs a greeting
BEGIN {
sayhello() # Call the function defined below
exit
}
function sayhello {
print "Hello World!" # Outputs a message to the terminal
}
Note that the awk extraction and reporting language is data driven and does not support arbitary line labels.
Axe
Function names (which are also labels) are global in Axe. They can be accessed from anywhere in any source file that gets compiled together.
BASIC
Line numbers are used instead of labels. These are also immediately accessible as soon as the line is entered, even if the program is not run:
GOTO 50: REM THIS WILL WORK IMMEDIATELY
The visibility of functions depends on the implementation. Most versions of basic will allow a function to be referenced from a point in the code prior to its definition. However, other implementations may require the function definition to be run, before it can be used:
10 DEF FN S(A)=A*A
20 PRINT FN S(2): REM THIS WILL WORK
30 PRINT FN C(2): REM CALLING A FUNCTION PRIOR TO DEFINITION MAY NOT WORK
40 GOSUB 9000
50 PRINT FN C(2): REM THIS WILL WORK
60 END
9000 DEF FN C(A)=A*A*A
9999 RETURN
bc
Functions have global scope and must be defined before usage. A defined function can be replaced with a newer definition later in the file. Recursive calls are possible because function are considered as defined within their own body.
There are no labels in bc.
f(1) /* First output line */
define f(x) {
return(x)
}
f(3) /* Second output line */
define f(x) {
return(x - 1)
}
f(3) /* Third output line */
- Output:
Runtime error (func=(main), adr=3): Function f not defined. 3 2
C
Demonstrating function scope as well as goto in a C program invariably leads to code like the one below. The Wikipedia article is a good starting point.
#include <stdio.h>
#define sqr(x) ((x) * (x))
#define greet printf("Hello There!\n")
int twice(int x)
{
return 2 * x;
}
int main(void)
{
int x;
printf("This will demonstrate function and label scopes.\n");
printf("All output is happening through printf(), a function declared in the header stdio.h, which is external to this program.\n");
printf("Enter a number: ");
if (scanf("%d", &x) != 1)
return 0;
switch (x % 2) {
default:
printf("Case labels in switch statements have scope local to the switch block.\n");
case 0:
printf("You entered an even number.\n");
printf("Its square is %d, which was computed by a macro. It has global scope within the translation unit.\n", sqr(x));
break;
case 1:
printf("You entered an odd number.\n");
goto sayhello;
jumpin:
printf("2 times %d is %d, which was computed by a function defined in this file. It has global scope within the translation unit.\n", x, twice(x));
printf("Since you jumped in, you will now be greeted, again!\n");
sayhello:
greet;
if (x == -1)
goto scram;
break;
}
printf("We now come to goto, it's extremely powerful but it's also prone to misuse. Its use is discouraged and it wasn't even adopted by Java and later languages.\n");
if (x != -1) {
x = -1; /* To break goto infinite loop. */
goto jumpin;
}
scram:
printf("If you are trying to figure out what happened, you now understand goto.\n");
return 0;
}
- Output:
Example run
This will demonstrate function and label scopes. All output is happening throung printf(), a function declared in the header stdio.h, which is external to this program. Enter a number: 5 You entered an odd number. Hello There! We now come to goto, it's extremely powerful but it's also prone to misuse. Its use is discouraged and it wasn't even adopted by Java and later languages. 2 times -1 is -2, which was computed by a function defined in this file. It has global scope within the translation unit. Since you jumped in, you will now be greeted, again! Hello There! If you are trying to figure out what happened, you now understand goto.
Delphi
1. Delphi is a one pass compiler, so the names of procedures, functions, variables, constants and types are only visible to code that comes after the item was declared. Procedure and functions can be "Forward" declared, which allows them to be declared before they are defined.
2. All items inside an object are visible throughout the object, no matter the order they are defined. Outside an object, the object and items inside it are only visible to code that comes after it was declared.
3. Delphi prodedures and functions can be nested. Varibles inside a procedure or function are only visible from inside the same procedures or functions. Variable, procedures and functions at higher levels of nesting are visible to lower levels of nesting.
4. Items inside objects have controlled visibility to the outside world. Objects are divided in specific sections that control the visibility of items inside the section. Here is a list of sections:
Private: Items contained within the "Private" section of an object are only visible inside the object.
Protected: Item contained within the "Protected" section of an object are only visible inside the object or inside object that inherit from the object.
Public: Item contained within the "Public" section of an object are completely visible to the outside world.
Published: Item contained within the "Published" section of an object are visible to the outside world and can be manipulated by the IDE.
// Test1 is visible to Test2, but not vice versa.
// The local variables A, B, and C invisible to the outside world.
procedure Test1;
var A,B,C: integer;
begin
end;
procedure Test2;
var A,B,C: integer;
begin
end;
// Test1 is visible to all code that follows it.
// Test2 is invisible to the ouside world
procedure Test1;
var A,B,C: integer;
procedure Test2;
var A,B,C: integer;
begin
end;
begin
end;
// Item1 and Test1 are only visible inside the object
// Item2 and Test2 are additional to inhered objects
// Item3 and Test3 are visible to the outside world
// Item4 is visible to the outside world and the IDE
type TMyObject = class(TObject)
private
Item1: integer
procedure Test1;
protected
Item2: integer
procedure Test2;
public
Item3: integer
procedure Test3;
published
property Item4: integer read FItem4 write FItem4;
end;
- Output:
Eiffel
Functions (routines which return a result), procedures (routines which have no result) and variables are considered features of a class and follow the same visibility rules. Eiffel allows for information hiding, where features can be selectively hidden from particular classes.
All features are assigned (at compile-time) to a particular scope defined by the most-recently preceding feature clause. Various feature clauses are given below, from least restrictive (most visible) to most restrictive (most hidden).
--assume A, B and C to be valid classes
class X
feature -- alias for "feature {ANY}"
-- ANY is the class at the top of the class hierarchy and all classes inherit from it
-- features following this clause are given "global" scope: these features are visible to every class
feature {A, B, C, X}
-- features following this clause are only visible to the specified classes (and their descendants)
-- classes not in this set do not even know of the existence of these features
feature {A, B, C}
-- similar to above, except other instances of X cannot access these features
feature {X}
-- features following this clause are only visible to instances of X (and its descendants)
feature {NONE}
-- NONE is the class at the bottom of the class hierarchy and inherits from every class
-- features following this clause are only visible to this particular instance of X
end
Erlang
The scope of an Erlang function is limited to the module where it is declared. It is possible to modify function scope by exporting a function from a module. There are no labels.
-module( a_module ).
-export( [exported_function/0] ).
exported_function() -> 1 + local_function().
local_function() -> 2.
Factor
Each word belongs to a vocabulary. Vocabularies may be added to the vocabulary search path to put their words in scope. For example, to use the +
word:
USE: math
2 2 +
Words are visible in the vocabulary where they are defined. But only after the point where they have been defined.
USE: io
IN: hello-vocab
hello ! error; hello hasn't been defined yet
: hello ( -- ) "Hello, world!" print ;
hello ! visible here
This restriction can be lifted through the use of DEFER:
.
USE: io
IN: hello-vocab
DEFER: hello
hello ! visible here
: hello ( -- ) "Hello, world!" print ;
hello ! visible here
FreeBASIC
PROCEDURES
A function
defines a block of code which can be executed with a single statement (a function call), and provide a value back to the caller when finished (a return value):
There are several reasons to use functions
- Reduces redundancy in your program.
- Enables reuse of code in many programs.
- Improves readability of the program.
- Improves maintainability of the program.
- Makes it easy to extend your program.
A subroutine
is a block of code which may be called at any time from a program.
This code may need to be executed multiple times, and subroutines provide an invaluable means to simplify code by replacing these blocks of code with a single subroutine call.
A subroutine also serves to allow a user to extend the FreeBASIC language to provide custom commands.
Many of the functions built into FreeBASIC are merely subroutines part of a "runtime library" linked to by default.
Scope (visibility) of a procedure through the different modules of a program.
A procedure is a subroutine (sub) or a function that can be called by code outside the procedure (or internal code in the case of a recursion).
A procedure consists of a sequence of instructions that form the body of the procedure.
It is possible to pass values or variables to a procedure, and a function may return a value or a reference.
Scopes of procedures in modules follows simple rules:
- Private scope: procedure visible only in its own module (where it is defined).
- Public scope: procedure visible from all modules constituting a compiled program (including static libraries).
- Export scope: when defined in a DLL (dynamically linked library), procedure visible from an external program that has loaded it (statically or dynamically).
LABELS
A label
defines a place in a program where Goto or GoSub can jump to.
A label can be a positive integer line number or a symbolname. In both cases, the label must start at the first column of line. A symbolname label must end with a colon (:) character.
Is available only in the "-lang qb" and "-lang fblite" dialect.
Go
Go is block scoped and has both functions and labels.
Functions can only be declared at the "top level" in a source file, that is, not nested or declared inside of anything else. This gives them "package scope," making them visible within a package (which can consist of multiple source files.) A They are not visible outside their package unless "exported." They are exported if the function name begins with an upper case letter, specifically Unicode class "Lu."
A "function literal" is different than a declaration. It is an expression that returns a function value, which can be assigned or passed around like any other value.
A function definition, either a top-level declaration or a function literal, represents a function block.
package main
import (
"fmt"
"runtime"
"ex"
)
func main() {
// func nested() { ... not allowed here
// this is okay, variable f declared and assigned a function literal.
f := func() {
// this mess prints the name of the function to show that it's an
// anonymous function defined in package main
pc, _, _, _ := runtime.Caller(0)
fmt.Println(runtime.FuncForPC(pc).Name(), "here!")
}
ex.X(f) // function value passed to exported function
// ex.x() non-exported function not visible here
}
package ex
import (
"fmt"
"runtime"
)
// X is exported.
func X(x func()) {
pc, _, _, _ := runtime.Caller(0)
fmt.Println(runtime.FuncForPC(pc).Name(), "calling argument x...")
x()
}
func x() { // not exported, x not upper case.
panic("top level x")
}
- Output:
ex.X calling argument x... main.func·001 here!
Labels can only be declared in function blocks. The scope is the function block where the label is declared excluding any nested function blocks.
package main
import "fmt"
func main() {
// labels loop and y both in scope of main
loop:
for false {
continue loop
}
goto y
y:
y := 0 // variable namespace is separate from label namespace
func() {
// goto loop ...loop not visible from this literal
// label y in outer scope not visible so it's okay to define a label y
// here too.
y:
for {
break y
}
y++ // regular lexical scoping applies to variables.
}()
fmt.Println(y)
}
// end: // labels not allowed outside function blocks
- Output:
1
haskell
Functions are considered global in haskell and can be referenced in the sections of code appearing before the function definition. The following code illustrates the same. add2 was declared after add3 and used in add3. The variables x,y and z are local to the function.
add3 :: Int -> Int-> Int-> Int
add3 x y z = add2 x y + z
add2 :: Int -> Int -> Int
add2 x y = x + y
main :: putStrLn(show (add3 5 6 5))
- Output:
ghci>main 16
In the function below the functions g and h are local to the function getSquaredSum. They cannot be called from anywhere outside the function.
getSquaredSum :: Int-> Int-> Int
getSquaredSum x y = g x + h y
where
g a = a*a
h b = b*b
- Output:
ghci> getSquaredSum 3 4 25 ghci>h 4 <interactive>: 115:1:error: Variable not in scope: h :: Integer -> t
Icon and Unicon
In both languages, function names (including procedure names - functions are language builtins while procedures are written in the language) have global scope. In Unicon, class methods are locally visible within the class but must be referenced through the class instance externally.
There are no labels in either language.
J
NAMES
J is scoped lexically but with non-nested block scope. Nesting can be emulated, where that is required. But deep nesting can be difficult to understand and debug so the coder is penalized (with a bit of extra work) for implementing deep nesting.
Specifically, J provides two scopes for user defined names:
Local scope, names defined using =. will have local scope if a block scope exists.
a=. 1
Locale scope, names defined using =: will have locale scope (and the base locale is used by default).
b=: 2
Names may include a locale qualifier. A locative is a qualified name. Locale qualifiers contain two _ characters, are a suffix on what would be the unqualified name. Locale qualifiers come in two forms: absolute and relative. Relative locale qualifiers use another name in the current locale to identify the target locale. Absolute locatives place the locale name between the two _ characters, while relative locatives name the locale reference following the pair of _ characters.
c_thingy_=: 3
d=: <'test'
e__d=: 4
b + e_test_
6
If a local definition exists for a name, it is an error to use use =: to assign that name (use a locative instead of the unqualified name if you really need to do this).
verb define ''
f=. 6
g=: 7
g=. 8
g=: 9
)
|domain error
| g =:9
Meanwhile, there is a global current locale (default: base) but each verb's definition is evaluated with the current locale being the locale where that verb was defined.
Name resolution first checks for local definitions for a name, and if none are found the current locale is checked, and if nothing is found there the current locale's search path is used to check other locales. By default the z locale is included as the last element of this path. (And, since the z locale contains the system defined words, removing it from a locale's path will break most things in that locale.)
The current locale during the execution of a verb is the locale where that verb was defined. But the current locale can be changed when the current named verb finishes using 18!:4
.
If you want to emulate static nested scope (or dynamic scope) you need to arrange for the desired behavior using the locale path mechanism.
LABELS
Labels are available in explicit definitions, and are names beginning with label_ and ending with a .. You may use them with a goto which is a name beginning with goto_ and ending with a .. Use of labels is restricted to the scope where they are defined, and they cannot be used to enter control structures (except in the sense of the normal entry point).
example=:3 :0
if. y do.
echo 0
goto_a.
echo 1
else.
echo 2
goto_a.
echo 3
end.
echo 4
label_a.
echo 5
)
example 1
0
5
example 0
2
5
jq
jq is scoped lexically.
A function can only be called within its definition or following it, it being understood that functions can in effect be passed by name as parameters to other functions.
A further restriction is that inner functions are invisible outside their enclosing function, an inner function being one which is defined within the body of another.
A function that is not defined within an inner function will be called a top-level function. The lowest-level function in which an inner function is defined will be called its enclosing function.
If more than one outer function has the same name, then the last definition effectively overwrites the first, at least as far as subsequent invocations are concerned.
A similar rule applies to two inner functions defined within the same enclosing function. Otherwise, inner functions of the same name can co-exist. In particular, a function named NAME may define an inner function of the same name. For example:
def NAME:
def NAME: 2;
1, NAME; # this calls the inner function, not the outer function
NAME # => 1, 2
Mutually Defined Functions The "declare-before-use" rule means that two top-level functions cannot be defined in terms of each other. Consider the following example:
def F(x): if x == 0 then M(x) else 1 end; # NOT POSSIBLE
def M(x): if x == 1 then F(x) else 2 end;
There are several possible workarounds using inner functions. For example, if both F and M must be top-level functions, we could define them as follows:
def F(x):
def M(x): if x == 1 then F(x) else 2 end;
if x == 0 then M(x) else 1 end;
def M(x): if x == 1 then F(x) else 2 end;
If F and M are not required to be top-level functions, then both F and M could be defined as inner functions of the same enclosing function.
Julia
In Julia, there is one type of global scope, defined as the scope of the individual module (module names can be exported or referenced by module name, but there is no global scope above module scope). User code not defined within a specific module has global scope within the predefined default module main. There are two types of local or nonglobal scope in Julia: hard local scope, which is the scope of variables defined within functions, and the "soft" local scope of variables within code structures, as quoted below from Julia's documentation:
Type of scope | block/construct introducing this kind of scope ---------------------------------------------------------------- Global Scope | module, baremodule, at interactive prompt (REPL) Local Scope | Soft Local Scope: for, while, comprehensions, try-catch-finally, let Local Scope | Hard Local Scope: functions (either syntax, anonymous & do-blocks), struct, macro
Hard local scope means that a variable defined within a function defaults to being local to
the function unless this is overridden with the global
keyword which allows
such a variable to reference a module-level global variable. Soft local scope means that variables
within such a code block reference variables of the same name in the parent scope unless the
variable is explicitly declared to be local with the local
keyword.
Julia uses lexical scoping, so the scope of a variable as defined above can be determined just by looking at the code where the variable was defined. Modules are nest-able within other modules and functions are nest-able within functions.
Kotlin
Functions in Kotlin can be declared at top level, within a class/object/interface or can be nested within another function.
Top level functions (i.e. functions declared outside any class) support three levels of visibility:
1. public - visible everywhere (the default if no modifier is used).
2. internal - visible anywhere within the same module.
3. private - visible only within the current file.
Functions declared within a class support four levels of visibility:
1. public - visible everywhere its class is visible (the default if no modifier is used).
2. internal - visible anywhere within the same module that its class is visible.
3. protected - visible only inside its class or any sub-classes thereof.
4. private - visible only inside its class.
Functions declared within an object (i.e. a singleton class) support the same levels of visibility as a normal class except for 'protected'.
Functions declared within an interface are usually public but can be private if they have a body.
Functions declared within another function do not have any visibility modifiers but are in scope from their point of declaration to the end of the enclosing function.
In Kotlin any expression can be marked with a label (an identifier followed by an @ sign). Currently, they are used with the 'break', 'continue' or 'return' keywords - to break out of the labelled loop, to continue with the next iteration of the labelled loop or to return from a labelled lambda expression, respectively.
Such labels are in scope from their point of declaration to the end of the corresponding block.
Labels can also be used with the 'this' keyword to distinguish between different outer scopes (classes or function receivers) where there is more than one to choose from.
The following program illustrates some of these usages.
// version 1.1.2
// top level function visible anywhere within the current module
internal fun a() = println("calling a")
object B {
// object level function visible everywhere, by default
fun f() = println("calling f")
}
open class C {
// class level function visible everywhere, by default
fun g() = println("calling g")
// class level function only visible within C
private fun h() = println("calling h")
// class level function only visible within C and its subclasses
protected fun i() {
println("calling i")
println("calling h") // OK as h within same class
// nested function in scope until end of i
fun j() = println("calling j")
j()
}
}
class D : C(), E {
// class level function visible anywhere within the same module
fun k() {
println("calling k")
i() // OK as C.i is protected
m() // OK as E.m is public and has a body
}
}
interface E {
fun m() {
println("calling m")
}
}
fun main(args: Array<String>) {
a() // OK as a is internal
B.f() // OK as f is public
val c = C()
c.g() // OK as g is public but can't call h or i via c
val d = D()
d.k() // OK as k is public
// labelled lambda expression assigned to variable 'l'
val l = lambda@ { ->
outer@ for (i in 1..3) {
for (j in 1..3) {
if (i == 3) break@outer // jumps out of outer loop
if (j == 2) continue@outer // continues with next iteration of outer loop
println ("i = $i, j = $j")
}
if (i > 1) println ("i = $i") // never executed
}
val n = 1
if (n == 1) return@lambda // returns from lambda
println("n = $n") // never executed
}
l() // invokes lambda
println("Good-bye!") // will be executed
}
- Output:
calling a calling f calling g calling k calling i calling h calling j calling m i = 1, j = 1 i = 2, j = 1 Good-bye!
Lua
In Lua, variables are global by default, but can be modified to be local to the block in which they are declared.
function foo() print("global") end -- global scope by default
foo()
local function foo() print("local module") end -- local to the current block (which is the module)
foo() -- local obscures the global
_G.foo() -- bug global still exists
do -- create a new block
foo() -- outer module-level scope still visible
local function foo() print("local block") end
foo() -- obscures outer module-level local
local function foo() -- redefine at local block level
print("local block redef")
local function foo() -- define again inside redef
print("local block redef inner")
end
foo() -- call block-level redef inner
end
foo() -- call block-level redef
end -- close the block (and thus its scope)
foo() -- module-level local still exists
_G.foo() -- global still exists
- Output:
global local module global local module local block local block redef local block redef inner local module global
M2000 Interpreter
There are 5 structures for named routines.
The Module (as a procedure) and the Function which use blocks {}. Each one define a scope. All entities defined inside erased, except the static types. We can define global modules/functions in any module or function. By default we define Local. We can't call something that is no global, or no as 1st child, or not a member of an object (if a module or function is a member of an object). Global names shadow any same name in the modules/function list, or if it is variable or array in the variable/array list. We can change the code of any module or function using a newer definition, except for those which are members of object and are marked as Final. In objects, modules and functions as members may be public or private. A private member is not private in a module or function as a member of the same type. Special case are the Operators for objects, these are private, except for expression evaluator. Modules and Functions may have static variables. Static variables are common for each call in a recursion type call. Static variables may differ as values for same function, because they saved to the caller object.
In a module or function we can bound at the end definitions, named Subroutines, and simple Functions. These definitions not used block and are at the end of the module's code or function's code. The simple functions called with @ before. The subs called as NameWithParenthesis(). We can define local variables, array, for temporary use modules and functions too.
The lambda function has a Variable name and a Function name. We can pass it as a value, so each lambda function because it is a function has own scope. Closures in a lambda are copied values. In a recursion call for lambda (we call it using Lambda()) the closures are common. Here we don't have connection to the caller object.
M2000 can make references to Functions, to Lambda Function but not for simple functions (which are bound to modules and functions). Lambda functions and Functions as members of objects can be passed by reference and they have access to object members.
Labels can be used in a module or function. Numbers or names. Names need a line for them, but numbers can exist with statements There are statements Goto and Gosub as in Basic, including On Goto and On Gosub. We can make simple routines using Return to return from them.We can jump out from a block of code. We can't do the opposite, to enter in a block of code from outside. We can't jump out of Module or Function block, we can exit only using Exit or Break statements (Break exit on multiple blocks, Exit exit the current block). So Goto used to exit from a specific inner block to some block above it.
Function Master {
Module Alfa {
Gosub 100
Global M=1000
\\ delta print 1000
delta
End
100 Print Module(Beta)=False
Print Module(Delta)=True
Return
}
Group Object1 {
Function Master {
=M
}
Module Final Beta {
\\ delta print 500
delta
alfa()
Sub alfa()
Local N=@Kappa(3)
Global M=N
\\ delta print 1500
Delta
Print This.Master()=1500
N=@Kappa(6)
\\ change value of M, not shadow M like Global M
M<=N
\\ delta print 9000
Delta
Print .Master()=9000
End Sub
Function Kappa(K)
=M*K
End Function
}
}
Module Global Delta {
Goto name1
\\ a remark here
name1:
Print Module(Alfa)=False
Print Module(Beta)=False
Print Module(Delta)=True
Print M
}
\\ This is the program
K=100
Global M=500
Alfa
Object1.Beta
Print Object1.Master()=500
Print K=100, M=500
}
Call Master()
\\ No variables exist after the return from Master()
Print Valid(M)=False
Nim
In Nim, procedures can be defined at the module level, which is the most frequent, or in any other scope, for instance in another procedure or even in a loop or an if statement. That means that, as regards scoping, procedures are managed as variables, types, etc.
When defined at the module level, a procedure is considered private to the module. To make it visible from other modules (provided they import the whole module or only the procedure), the procedure must be annotated with an “*”.
Labels are only used when defining a block which opens a new scope: block outer:
. This label is only used to allow breaking from the block (useful when we want to exit from internal loops): break outer
. The label is only visible in the block.
Note that blocks are allowed anywhere where code is allowed, and so are labels. This is perfectly valid:
const C = block useless: 3
Objeck
In Objeck function, names may be public or private. Access to the classes that contain functions can be explicit or controlled at the file level by "use" statements.
Oforth
Functions are global and must be defined before use. Methods are global and must be declared before use. They can be used before a method implementation.
Perl
Perl allows various ways to futz with scope, but keeping it simple: Routines are package-scoped, and in each package the final definition of the routine is the one that is used throughout. Labels are generally also package-scoped, except when it comes to goto
; let's don't even go there.
no warnings 'redefine';
sub logger { print shift . ": Dicitur clamantis in deserto." }; # discarded
logger('A'); # can use before defined
HighLander::logger('B'); # ditto, but referring to another package
package HighLander {
logger('C');
sub logger { print shift . ": I have something to say.\n" }; # discarded
sub down_one_level {
sub logger { print shift . ": I am a man, not a fish.\n" }; # discarded
sub down_two_levels {
sub logger { print shift . ": There can be only one!\n" }; # routine for 'Highlander' package
}
}
logger('D');
}
logger('E');
sub logger {
print shift . ": This thought intentionally left blank.\n" # routine for 'main' package
};
- Output:
A: This thought intentionally left blank. B: There can be only one! C: There can be only one! D: There can be only one! E: This thought intentionally left blank.
Phix
Functions are private (restricted to a single file) by default, or can be made global by prefixing the definition with the global keyword to make it visible everywhere.
Functions within classes are either private (can only be called from within the class definition) or public (can be called by anything that manages to get it's grubby little mitts on an instance of it). The containing classes themselves can be private or public as above, but if an instance of a private class is handed over, any recipient has full access to anything declared as public within it (but naturally they won't have the ability to create an instance of a private class).
There are no labels in Phix except for inline assembly code. Top-level #ilASM{} can use the special syntax :% (also :<, :>, and :!, see pops.e for details) to declare global labels, typically opcodes such as :%opAlloc, otherwise normal labels, declared with :: syntax, are [only] visible across all #ilASM{} in the same file or routine.
PL/I
Functions are normally internal to a program. If they are at the nesting level
immediately within the program, they are accessible from anywhere in the program.
Functions can also be encapsuled in a package, and the function name exported.
Functions can be compiled separately, and then linked with a program
in which case they are globally accessible.
PowerShell
A function exists in the scope in which it was created.
If a function is part of a script, the function is available to statements within that script. By default, a function in a script is not available at the command prompt.
You can specify the scope of a function. For example, the function is added to the global scope in the following example:
function global:Get-DependentService
{
Get-Service | Where-Object {$_.DependentServices}
}
When a function is in the global scope, you can use the function in scripts, in functions, and at the command line.
Functions normally create a scope. The items created in a function, such as variables, exist only in the function scope.
For more information about scope in Windows PowerShell, see about_Scopes
Get-Help about_Scopes
Python
- In Python; our chief creator of new scopes is a function definition ... functions and classes... classes and functions... Our two creators are functions and classes... and files... Our three creators are ... I'll come in again.
Some (rather dry) rules are:
- All names, (of functions, classes, as well as variables), are scoped in the same way.
- A names scope is its closest enclosing file, function, or class.
- Names belong to the scope where they are assigned-to (or bound)
- Cf.
- Ka-Ping Yee has a tutorial on the above here.
- This Python Enhancement Proposal: PEP 3104 introduces the non-local keyword of Python 3.
- And of course, this!
Racket
Racket inherits the strict lexical-scopedness of Scheme, so function bindings (like any other bindings) are visible only within their scope. For example
(define (foo x)
(define (bar y) (+ x y))
(bar 2))
(foo 1) ; => 3
(bar 1) ; => error
but that applies only to the *bindings* -- the actual function values (like other values) can be passed around freely:
(define (foo x)
(define (bar y) (+ x y))
bar)
(foo 1) ; => #<procedure:bar>
((foo 1) 2) ; => 3
But it should be noted that Racket is flexible enough to make it possible to implement other kinds of scope.
Raku
(formerly Perl 6)
First a little hand-wavey exposition. The lines are rather blurry in Raku between subroutines, methods, operators and functions. Methods are associated with an object and are inheritable. Subroutines and operators are not. Other than that though there is a lot of overlap. "A function" doesn't really have a specific definition, but is more of a generic term used when talking about code reference type of things.
Methods don't have a separate scope from the object they are attached to. If the object is in scope, the method will be.
A subroutine is really just another type of object. It has a code reference and has ROUTINE semantics attached to it. The same holds for operators. Operators are really just subroutines with a funny calling convention. That being the case, scoping for subroutines very closely follows scoping rules for any other Raku variable type.
In general, subroutines are "my" variables by default (if you don't specify, the "my" is implicit), meaning scoping is lexical to the enclosing block and flows inward. A subroutine defined within a block will be visible to everything inside that block, even other blocks within that block. However, any inner block can define its own subroutine with the same name and that will be used in preference to the routine from an outer block. That implies you can easily override / redefine core functions from the Raku setting. The setting is the collection of built in functions supplied by Raku, typically and somewhat incongruously referred to as "CORE" even though technically it is the outermost scope. ( SKIN? BARK? CRUST? ... oooo! EXOSKELETON! :-) )
Alternately, subroutines may be declared as an "our" variable making it a package global, visible anywhere in the packages' namespace. That is somewhat discouraged though as it pollutes the namespace and reduces the granularity of control.
There are several ways to modify the relative scope of a subroutine (any item in the symbol table really) by adding modifiers to the name.
CALLER # Contextual symbols in the immediate caller's lexical scope OUTER # Symbols in the next outer lexical scope UNIT # Symbols in the outermost lexical scope of compilation unit SETTING # Lexical symbols in the unit's DSL (usually CORE) PARENT # Symbols in this package's parent package (or lexical scope)
# call a routine before it has been defined
say log(); # prints: outer
# define a subroutine that overrides a CORE function
sub log { 'outer' };
{
# redefine the subroutine in this block
sub log { 'inner' };
{
# redefine the subroutine yet again
sub log { 'way down inside' };
# call it within this block
say log(); # prints: way down inside
# call it from the block one level out
say &OUTER::log(); # prints: inner
# call it from the block two levels out
say &OUTER::OUTER::log(); # prints: outer
# call it from the outermost block
say &UNIT::log(); # prints: outer
# call a subroutine that is post declared in outermost scope
outersub()
}
{
# subroutine in an inner block that doesn't redefine it
# uses definition from nearest enclosing block
say log(); # prints: inner
}
# call it within this block
say log(); # prints: inner
# call it from the block one level out
say &OUTER::log(); # prints: outer
}
sub outersub{
# call subroutine within this block - gets outer sub
say log(); # prints: outer
# call subroutine from the scope of the callers block
say &CALLER::log(); # prints: way down inside
# call subroutine from the outer scope of the callers block
say &CALLER::OUTER::log(); # prints: inner
# call the original overridden CORE routine
say &CORE::log(e); # prints: 1 ( natural log of e )
}
Labels are less interesting and are typically useful only for control flow in looping constructs. They generally follow the same scoping rules as "my" variables. There is nearly always easier ways to do control flow though, so they aren't heavily used.
REXX
In REXX, labels (which are also the name of in-stream procedures (or subroutines or functions) are identified by:
- (optional blanks)
- a REXX symbol
- (optional blanks)
- a colon (:)
- (optional blanks)
- (optional REXX statement (;)
- (optional semicolon (;)
- (optional blanks)
(all of the above are normally contained on one line (record), but may (syntactically) be continued by the normal REXX rules for continuation.
Any label can be referenced from anywhere in the REXX program (global scope).
Multiple labels (with the same name) are not considered an error in the REXX language; the first label found (topmost) is used.
REXX comments may be added anywhere blanks can be used.
Multiple labels may be specified on the same line with:
- (optional blanks)
- a REXX symbol
- (optional blanks)
- a colon (:)
- (optional blanks)
- ────(a repeat of the above as many times as is possible on a line of code)────
- (optional blanks)
/*REXX program demonstrates the use of labels and also a CALL statement. */
blarney = -0 /*just a blarney & balderdash statement*/
signal do_add /*transfer program control to a label.*/
ttt = sinD(30) /*this REXX statement is never executed*/
/* [↓] Note the case doesn't matter. */
DO_Add: /*coming here from the SIGNAL statement*/
say 'calling the sub: add.2.args'
call add.2.args 1, 7 /*pass two arguments: 1 and a 7 */
say 'sum =' result /*display the result from the function.*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
add.2.args: procedure; parse arg x,y; return x+y /*first come, first served ···*/
add.2.args: say 'Whoa Nelly!! Has the universe run amok?' /*didactic, but never executed*/
add.2.args: return arg(1) + arg(2) /*concise, " " " */
output
calling the sub: add.2.args sum = 8
Ring
# Project : Scope/Function names and labels
see "What is your name?" + nl
give name
welcome(name)
func welcome(name)
see "hello " + name + nl
Output:
What is your name? CalmoSoft hello CalmoSoft
Ruby
'def' starts the definition of a method, and 'end' ends it - no cute little curly braces.
def welcome(name)
puts "hello #{name}"
end
puts "What is your name?"
$name = STDIN.gets
welcome($name)
return
output
What is your name? xyz hello xyz
Scala
object ScopeFunction extends App {
val c = new C()
val d = new D()
val n = 1
def a() = println("calling a")
trait E {
def m() = println("calling m")
}
a() // OK as a is internal
B.f() // OK as f is public
class C {
// class level function visible everywhere, by default
def g() = println("calling g")
// class level function only visible within C and its subclasses
protected def i() {
println("calling i")
println("calling h") // OK as h within same class
// nested function in scope until end of i
def j() = println("calling j")
j()
}
// class level function only visible within C
private def h() = println("calling h")
}
c.g() // OK as g is public but can't call h or i via c
class D extends C with E {
// class level function visible anywhere within the same module
def k() {
println("calling k")
i() // OK as C.i is protected
m() // OK as E.m is public and has a body
}
}
d.k() // OK as k is public
object B {
// object level function visible everywhere, by default
def f() = println("calling f")
}
val l = (i:Int, j: Int) => println(i,j)
println("Good-bye!") // will be executed
}
Sidef
In Sidef, the same rule which is applied to variable scoping, is applied to functions and classes as well, which means that a function defined inside another function is not visible outside the current scope.
# Nested functions
func outer {
func inner {}; # not visible outside
}
# Nested classes
class Outer {
class Inner {}; # not visisble outside
}
Tcl
There are a number of different symbol types in Tcl, all of which are handled independently. Each namespace contains a mapping from (simple) command names to command implementations; when a command is looked up, the search is done by looking in the current namespace, then in the namespaces on that namespace's path (which is usually empty), and finally in the global namespace. There are no local commands (unlike with variables, though a lambda expression in a variable can act very similarly to a command). Commands only have a mapping after they have been created; the proc
“declaration” is just a command that creates a procedure at the point where it is called.
doFoo 1 2 3; # Will produce an error
proc doFoo {a b c} {
puts [expr {$a + $b*$c}]
}
doFoo 1 2 3; # Will now print 7 (and will continue to do so until doFoo is renamed or deleted
Tcl does not support labels, either outside or inside procedures. (Other mechanisms are used for jumps and state machines.)
UNIX Shell
There is no lookahead in the shell, so functions cannot be called until their definition has been run:
#!/bin/sh
multiply 3 4 # This will not work
echo $? # A bogus value was returned because multiply definition has not yet been run.
multiply() {
return `expr $1 \* $2` # The backslash is required to suppress interpolation
}
multiply 3 4 # Ok. It works now.
echo $? # This gives 12
The shell does not support the use of arbitrary line labels.
V (Vlang)
Vlang has both functions and labels.
A function definition, either a top level declaration or a function literal, represents a function block.
fn world() {
print("World!")
}
fn main() {
// anonymous function
f := fn() {
print("Hello ")
}
f() // "Hello
world() // World!"
// "Hello World!"
}
Functions can be used before their declaration (below main), but can still be called from main.
This eliminates the need for header files or worrying about the order.
fn main() {
println(add(77, 33))
println(sub(100, 50))
}
fn add(x int, y int) int {
return x + y
}
fn sub(x int, y int) int {
return x - y
}
Functions are private (not exported) by default. To allow other modules to use them, prepend pub
pub fn public_function() {
}
fn private_function() {
}
Labelled break & continue:
You can also use break and continue followed by a label name to refer to an outer for loop.
outer: for i := 4; true; i++ {
println(i)
for {
if i < 7 {
continue outer
} else {
break outer
}
}
}
Goto and labels:
1) The label name must be contained within the same function as the 'goto' statement.
2) Used only with 'unsafe' statements.
// Unsafe 'goto' pseudo example:
if x {
// ...
if y {
unsafe {
goto my_label
}
}
// ...
}
my_label:
Wren
Firstly, Wren doesn't support labels at all.
Secondly, functions (as opposed to methods) are first-class objects and have the same visibility as any other object. In other words, when defined in a particular scope, they are visible from the point of declaration to the end of that scope.
On the other hand, methods are always public members of a class and are visible throughout that class. Although technically a top-level class is visible throughout the module in which its defined, it is null prior to its definition.
The following example illustrates these points.
//func.call() /* invalid, can't call func before its declared */
var func = Fn.new { System.print("func has been called.") }
func.call() // fine
//C.init() /* not OK, as C is null at this point */
class C {
static init() { method() } // fine even though 'method' not yet declared
static method() { System.print("method has been called.") }
}
C.init() // fine
- Output:
(as it stands) func has been called. method has been called. (with line 1 uncommented) [./Scope_Function_names_and_labels line 3] Error at '}': Variable 'func' referenced before this definition (first use at line 1). (with only line 7 uncommented) func has been called. Null does not implement 'init()'. [./Scope_Function_names_and_labels line 7] in (script)
XPL0
Function names follow the scoping rules of Algol. A function is a procedure that returns a value.
A procedure name is visible from the point it's declared to the end of the procedure in which its declaration appears. A complete program is a procedure, informally called "main."
A procedure name is also visible in any sub-procedures that might be nested in the procedure. If the same name is declared at different levels in nested procedures, the most local declaration is used. Procedures can be nested up to eight levels deep.
There are no labels in XPL0 (except for inline assembly code).
zkl
zkl has no labels.
Functions have two modifiers, public (the default) and private. Private is the same as public inside the compilation unit, outside that unit/file, a private function can only be accessed via reflection.
class C{ fcn [private] f{} }
ZX Spectrum Basic
Functions are visible as soon as they are entered, even if the program is not run. Line numbers are used instead of labels. These are also immediately accessible as soon as the line is entered, even if the program is not run:
9000 REM The function is immediately visible and usable
9010 DEF FN s(x)=x*x
PRINT FN s(5): REM This will work immediately
GO TO 50: REM This will work immediately
- Programming Tasks
- Basic language learning
- Scope
- 6502 Assembly
- ALGOL 68
- ALGOL W
- AWK
- Axe
- BASIC
- Bc
- C
- Delphi
- SysUtils,StdCtrls
- Eiffel
- Erlang
- Factor
- FreeBASIC
- Go
- Haskell
- Icon
- Unicon
- J
- Jq
- Julia
- Kotlin
- Lua
- M2000 Interpreter
- Nim
- Objeck
- Oforth
- Perl
- Phix
- Phix/basics
- PL/I
- PowerShell
- Python
- Racket
- Raku
- REXX
- Ring
- Ruby
- Scala
- Sidef
- Tcl
- UNIX Shell
- V (Vlang)
- Wren
- XPL0
- Zkl
- ZX Spectrum Basic
- GUISS/Omit