Prev Next

Names and Name Binding [Chapter 7]

Identifiers

Names are called identifiers. The rules for building identifiers differ from one programming language to another. In Scheme, **$ is an identifier.

Simple naming

After you create something (often an anonymous thing) you can typically give it a name so that you can refer to it. I will use Astarte for some examples. In Astarte, you can write

 Let five = 3+2.
to give a name (five) to the number 5, and
 Let x = y.
makes x be another thing for the same thing that y names.

Astarte expression (?x => 2*x) creates an anonymous function that returns twice its input. You can give this function a name.

 Let twice = (?x => 2*x).
Now computing twice(5) yields 10. It was not necessary to give the function a name, though. Expression
 (?x => 2*x)(5)
has value 10. Names are a convenience rather than a requirement.

Tying together naming and creation

Some languages combine creating something with giving it a name, and in some cases it is not possible to create certain kinds of things without also giving them names.

Example: variables

In C++, declaration
 int x;
creates a variable and gives it a name (x). Normally, you combine creation of a variable with giving a name to the variable. If you like, you can give a new name to an old variable in C++, but a special mechanism is provided for that, rather than relying on one naming mechanism as Astarte does. Declaration
 int& y = x;
makes y another name for variable x, and anything you store in y will be put in x.

Example: functions

C++ also combines creation of a function with naming it. You write

 int twice(int x)
 {
   return 2*x;
 }
to create a new function and to call it twice. This is a fundamental notation in C++. Astarte takes an approach of providing an abbreviation that looks similar to this in some ways.
 Let twice(?x) = 2*x.
abbreviates
 Let twice = (?x => 2*x).

C++ does not have a way to say that one function is the same as another. In Astarte, you just use a Let to do that:

  Let dbl = twice.
Ada provides a special notation for that. In Ada, you write
 function Dbl(X: Integer) return Integer 
   renames Twice;

Pattern matching

Mathematicians often specify values implicitly by giving equations. For example, equation

  2x + 1 = 7
is a way of saying that x = 3. Some programming languages provide a similar facility, called pattern matching. In Astarte, writing
  Match 2 * ?y + 1 = 7.
has the same effect as
  Let y = 3.
In an Astarte pattern match, you decorate each thing that is to be solved for with a question mark.

Pattern matching is useful in several places. One is to get pieces of a complex value. For example,

  Let lst = [2,5,8].
  Match [?a,?b,?c] = lst.
binds a = 2, b = 5 and c = 8. It is not necessary to make explicit use of functions that extract the parts. Used well, pattern matching makes a program more readable.

You cannot use just any equation. The compiler knows how to solve a limited class of equations. The Astarte pattern matching facility allows combining of equations. For example, two kinds of equations that the compiler knows how to solve are

  Match ?n+1 = m.
  Match [?a,?b] = lst.
You can combine these forms, yielding
  Match [?n+1,?b] = lst
If lst is [5,2], this will bind n = 4 and b = 2.

Caution: Pattern matching really is solving equations. Pattern match

  Match ?n+1 = 8.
binds n = 7, not n = 9. The solution to equation n+1 = 8 is n = 8-1. In general, the pattern match facility has to employ inverse operations. Subtraction is, in a sense, the opposite of addition, so addition in a pattern match is translated to a subtraction for the purposes of solving the equation.

Pattern matches do not always succeed. For example,

 Match [?a,?b] = [1,2,3].
fails since a list of length 2 cannot equal a list of length 3. We will see later how to deal with failed pattern matches.

Astarte pattern matches allow a variable to occur twice.

  Match [?x,?x] = lst
only succeeds of lst is a list of two identical values. You can also include constants in pattern matches.
  Match [0,?x] = lst.
only succeeds if lst is a list of two values, where the first one is 0.

Overloading

In natural languages such as English it is common to give more than one meaning to a word. (Look up "place" in a dictionary. My dictionary has 42 definitions.) It can be convenient to do the same thing in a programming language. When a name has more than one meaning, it is said to be overloaded.

Even the first higher level language, Fortran, made limited use of overloading. There were two different addition instructions, one that adds integers, the other that adds floating point numbers, and the designers of Fortran wanted to use the + symbol to name both of them. So in

  N = M + 1
  X = Y + 1.0
the first line might call for integer addition, but the second for floating point addition. The compiler uses type information to determine which meaning is intended. Since M and 1 have type INTEGER, integer addition is used.

Fortran does not allow a programmer to create his or her own overloaded definitions. C++ does allow that, though. You can define

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

  double twice(double x)
  {
    return 2*x;
  }
There is no requirement that the two definitions have the same effect, but usually you use overloading in cases where you, the programmer, think of two operations as the same, even though they might need to be implemented differently in the program.


Prev Next