Scope/Function names and labels

From Rosetta Code
Revision as of 08:01, 1 November 2014 by Peak (talk | contribs) (jq)
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>

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

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>

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. A further restriction is that inner functions are invisible outside their enclosing function.

An inner function is 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. 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>

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 subroutines (or functions) are identified by:

  • (optional blanks), a REXX symbol, (optional blanks), a colon (:)

Labels (and therefore subroutines/functions/procedures) are global in scope, though local to the REXX program, that is, any label can be referenced from anywhere in the REXX program. <lang rexx>/*REXX program demonstrates use of labels and a CALL. */ zz=4 signal do_add ttt=sinD(30) /*this REXX statement is never executed.*/

do_add: /*coming here from the SIGNAL statement.*/

say 'calling the sub add.2.args' call add.2.args 1,7 say 'sum=' result exit /*stick a fork in it, 'cause we're done.*/

add.2.args: procedure; parse arg x,y; return x+y</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>