3. Names and Bindings

3.1. Names in a program

We need names (or identifiers ) in order to denote various entities in a program.

  • Syntax of names differs depending on the language. In most languages, a name is a sequence of alphabets, numbers and some symbols.

  • In some languages, there is a limit on the length of names.

  • There are case-sensitive languages and case-insensitive languages.

A Keyword is a name which plays some designated role in syntax. A reserved word is a keyword which cannot be used with other meaning.

Fortran has no reserved word

The following Fortran program is syntactically correct.

INTEGER REAL
REAL INTEGER
REAL = 3
INTEGER = 1.2

Most languages provide standard libraries. Names defined in those libraries are neither keywords nor reserved words.

Names defined in libraries

In Javascript, alert function is provided by browsers. We can use the name alert for other purpose.

var alert;
alert = 1;

3.2. Namespace

When we use a lot of names, it is necessary to use long names in order to avoid conflicts. However, long names are not convenient to read and write. A namespace is a name given to a set of names, which allows us to make the hierarchy of names. In other words, it enables us to use concatenated short names instead of a single long name.

Namespace in C++

:: is the operator to concatenate names.

#include <iostream>

main() {
  std::cout << "Hello, world!\n";
}

We can set the default namespace by using namespace.

#include <iostream>
using namespace std;

main() {
  cout << "Hello, world!\n";
}

Importing a module in Python

If you import a module, names defined in the module are available in the form module.function.

import foo
x = foo.bar()

If you import a function, the function name is available without the module name.

from foo import bar
x = bar()

3.3. Bindings

3.3.1. Definition of bindings

Because a name is a syntactic object, we must make a connection between a name and a semantic entity (e.g. variable, function, etc.).

  • A binding is a link between a name (more precisely, an occurence of a name) and a certain semantic entity.

    • We call a binding static when it can be determined before execution (usually compile-time).

    • We call a binding dynamic when it is determined during execution.

  • An environment is a set of bindings currently used during execution.

Note

A static binding does not necessarily mean a certain name always bound to the same entity. Different occurences of a certain name may have different bindings.

Variables in TinyBASIC

TinyBASIC (very small BASIC interpreter) has only 26 variables: A to Z. In this case, we always use the same environment.

Variables in Java

In Java, a variable declaration int i; means we will bind a name i to a newly created integer variable.

Exercise 5

There are two types of languages as to varibale declarations. Languages such as C and Java require declarations before variables are used, while languages such as Perl and Ruby do not. What are merits and demerits of these two types of languages?

[Answer]

3.3.2. Anonymous and alias

Bindings are not necessarily one-to-one association.

  • We call an entity anonymous if it is not bound to any name.

  • One entity can be bound to more than one names. In such case, names that bound to the same entity are called alias of each other.

Anonymous function in JavaScript

function(x) { return x+1; }

Anonymous function in Lisp

(lambda (x) (+ x 1))

Alias in Ruby

alias $b $a
$a = 2
puts $b

3.4. Scope

A scope is a part of program where a certain binding is used (in other words, we can see an entity through its name).

3.4.1. Static Scoping

In Algol-based languages, the scope of a name is a block in which the name is declared. If the same name is declared more than once, the most inner one takes precedence over outer ones. This type of scoping is also called lexical scoping because it is determined by the lexical stuructres.

Static scoping

Both procedure main and procedure sub2 have variable definitions of x. Occurences of x in procedure sub1 use the variable defined in procedure main.

procedure main;
  var x : integer;    { declaration 1 }

  procedure sub1;
    begin
      ... x ...       { refers declaration 1 }
    end;

  procedure sub2;
    var x : integer;  { declaration 2 }
    begin
      ... x ...       { refers declaration 2 }
    end;

  { body of main }
  begin
    ... x ...         { refers declaration 1 }
  end;

3.4.2. Dynamic scoping

In the original Lisp and some of its successor, if a name is declared in a function, its scope extends to other functions called from it. If the same name is declared more than once, the most recent one takes precedence over older one.

Dynamic scoping

Occurrences of x in procedure sub1 have different bindings depending on which procedure calls sub1.

procedure main;
  var x : integer;  { declaration 1 }

  procedure sub1;
    begin
      ... x ...     { refers declaration 1 when called from B
                      refers declaration 2 when called from A }
    end;

  procedure sub2;
    var x : integer;  { declaration 2 }
    begin
      sub1          { call A }
    end;

  { body of main }
  begin
    sub1;           { call B }
    sub2
  end;

Exercise 6

In the following pseudo code, what is the output when using staic scoping and dynamic scoping, respectively?

procedure main;
  var x : integer;

  procedure sub1;
    begin
      writeln(x)  { output the value of x }
    end;

  procedure sub2;
    var x : integer;
    begin
      x := 10;
      sub1
    end;

  begin
    x := 5;
    sub2
  end.

[Answer]