Scope/Function names and labels: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 119: Line 119:
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|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).
<lang Eiffel>--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</lang>



=={{header|Erlang}}==
=={{header|Erlang}}==

Revision as of 01:59, 19 February 2015

Task
Scope/Function names and labels
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to 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

AWK

In awk, function names are always global and can be referenced in sections of code appearing before the definition: <lang awk># This program outputs a greeting BEGIN {

 sayhello()    # Call the function defined below
 exit

}

function sayhello {

  print "Hello World!"    # Outputs a message to the terminal

}</lang> Note that the awk extraction and reporting language is data driven and does not support arbitary line labels.

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: <lang basic>GOTO 50: REM THIS WILL WORK IMMEDIATELY</lang> 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: <lang basic>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</lang>

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.

<lang 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 */</lang>

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.

<lang C> /*Abhishek Ghosh, 8th November 2013, Rotterdam*/

  1. include<stdio.h>
  1. define sqr(x) x*x
  2. define greet printf("\nHello There !");

int twice(int x) { return 2*x; }

int main() { int x; printf("\nThis will demonstrate function and label scopes."); printf("\nAll output is happening throung printf(), a function declared in the header file stdio.h, which is external to this program."); printf("\nEnter a number : "); scanf("%d",&x);

switch(x%2){ default:printf("\nCase labels in switch statements have scope local to the switch block."); case 0: printf("\nYou entered an even number."); printf("\nIt's square is %d, which was computed by a macro. It has global scope within the program file.",sqr(x)); break; case 1: printf("\nYou entered an odd number."); goto sayhello; jumpin: printf("\n2 times %d is %d, which was computed by a function defined in this file. It has global scope within the program file.",x,twice(x)); printf("\nSince you jumped in, you will now be greeted, again !"); sayhello: greet if(x==-1)goto scram; break; };

printf("\nWe now come to goto, it's extremely powerful but it's also prone to misuse. It's use is discouraged and it wasn't even adopted by Java and later languages.");

if(x!=-1){ x = -1; /*To break goto infinite loop.*/ goto jumpin; }

scram: printf("\nIf you are trying to figure out what happened, you now understand goto."); return 0; }

</lang>

Output:

Example run

This will demonstrate function and label scopes.
All output is happening throung printf(), a function declared in the header file 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. It's 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 program file.
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.

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). <lang Eiffel>--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</lang>


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.

<lang Erlang> -module( a_module ).

-export( [exported_function/0] ).

exported_function() -> 1 + local_function().

local_function() -> 2. </lang>

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.

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

}</lang> <lang go>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")

}</lang>

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. <lang go>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</lang>

Output:
1

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.

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: <lang jq>def NAME:

 def NAME: 2;
 1, NAME;  # this calls the inner function, not the outer function

NAME # => 1, 2</lang>

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: <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;</lang> 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: <lang jq>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;</lang> 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.

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 6

First a little hand-wavey exposition. The lines are rather blurry in Perl 6 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 Perl 6 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 Perl 6 setting. The setting is the collection of built in functions supplied by Perl 6, 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)

<lang perl6># call a routine before it has been defined say log(); # prints: outer

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

}</lang>

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.

PL/I

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

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:

  1. All names, (of functions, classes, as well as variables), are scoped in the same way.
  2. A names scope is its closest enclosing file, function, or class.
  3. 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 <lang racket> (define (foo x)

 (define (bar y) (+ x y))
 (bar 2))

(foo 1) ; => 3 (bar 1) ; => error </lang> but that applies only to the *bindings* -- the actual function values (like other values) can be passed around freely: <lang racket> (define (foo x)

 (define (bar y) (+ x y))
 bar)

(foo 1)  ; => #<procedure:bar> ((foo 1) 2) ; => 3 </lang>

But it should be noted that Racket is flexible enough to make it possible to implement other kinds of scope.

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 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 is used. <lang rexx>/*REXX program demonstrates use of labels and a CALL statement. */ zz=4 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 exit /*stick a fork in it, 'cause we're done.*/ /*────────────────────────────────subroutines (or functions)────────────*/ add.2.args: procedure; parse arg x,y; return x+y

add.2.args: say 'Whoa Nelly!! Has the universe run amok?'

                                         /* [↑]  dead code, never XEQed*/

add.2.args: return arg(1) + arg(2) /*concise, but never executed.*/</lang> output

calling the sub:  add.2.args
sum = 8

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. <lang ruby># Nested functions func outer {

   func inner {};   # not visible outside

}

  1. Nested classes

class Outer {

   class Inner {};  # not visisble outside

}</lang>

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. <lang tcl>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</lang> 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:

<lang sh>#!/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</lang>

The shell does not support the use of arbitrary line labels.

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. <lang zkl>class C{ fcn [private] f{} }</lang>

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: <lang zxbasic>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</lang>