CSE130 LECTURE NOTES

October 11, 1999
 
 

ADMINISTRATION

Please do use the course bulletin board for questions inspired by the lectures or the assignment.

If you do not have exactly two team-mates for the first project, you need to find a third person or a team to join immediately.

On Thursday I'll talk about why the ability to write high-quality reports is so important for computer scientists and software engineers.  For today, here are some concrete guidelines.
 
 

REPORT GUIDELINES

First, your report should be printed on standard 8.5 inch by 11 inch paper using a laser printer or a high-quality inkjet printer.  You should use text processing software such as Microsoft Word, which is available on UCSD Macintosh computers for free student use.  Each report should be stapled together securely, with no binders or sleeves.

Reports should be as long as necessary to be complete and easy to read, but they should be concise.  The maximum length permitted is ten pages, single-spaced.

Reports should be organized well:

Reports should be written well: If you follow all these guidelines, you will produce a good report.
 
 

 AN ARRAY IS A MAPPING

A mapping is a mathematical object.  An array is one way of implementing a mapping computationally.

Mathematically, a mapping from set A to set B is a set of ordered pairs where

(1) the first item in each pair is from A and the second item is from B
(2) for each item x in A, there is a unique y in B such that the pair <x,y> is in the mapping.

Note that an array satisfies exactly these two properties:

Traditional programming languages only allow index sets to be finite. This ensures that any value of the mapping type can be stored in memory.

Often the restriction is even more extreme: an index type must be a Cartesian product of discrete finite types.  For example, the following type might be used to store a screen image with 24-bit color:

        type screen = array [0..1023, 0..767] of array[1..3] of byte;

Remember that an array is a composite value.  We could have

        var blank : screen;
 
 

INFINITE MAPPINGS

The notation for denoting the set of all mappings from one set to another is ->. For example, cosine is a member of R -> R.  (Note that the words function and mapping are synonyms.)

Note that A -> (B -> C) is equivalent to (A x B) -> C but different from (A -> B) -> C.

Consider the mapping type string -> integer.  A variable of this type might be convenient for storing student scores on a quiz, for example.  No standard language allows this type. However some languages that are biased towards ease-of-use rather than efficiency do, for example the awk language.

Data structures question: how is a variable of type string -> integer implemented?  Answer: maybe a labeled binary tree sorted in "in-order", or by hashing.
 
 

PL FUNCTIONS ARE VALUES OF A MAPPING TYPE ALSO

In standard PLs, we can't have a variable odd of type array [integer] of boolean so that
odd[-1] = true
odd[0] = false
odd[1] = true
and so on.  But we can have a programming language function odd so that
odd(-1) = true
odd(0) = false
odd(1) = true
and so on.

Notice that the function odd could have two different implementations.  One implementation might use mod, while the other might subtract or add two until 0 or 1 is reached.
 
 

OBSERVATIONS ABOUT FUNCTION VALUES

Many languages have many different syntaxes for creating mappings. Consider
type boolean = {false, true};

const not1: array [boolean] of boolean := [true, false];

function not2 (x: boolean): boolean;
begin
    if x then return false else return true;
end;

Conceptually not1 and not2 both have the same mapping type, i.e. boolean -> boolean.

Functions really are values similar to numbers and records. They just happen to be usually infinite. However, functions are typically not first-class values.

Definition: A first-class value is one that can be assigned to a variable, passed as a parameter, returned as the result of a function, and included in a larger composite value, just like other values.

In typical PLs, being "first-class" is not all-or-nothing.  Some values are "more first-class" and some values are "less first-class."  The property that the fewest values usually possess is the ability to be returned as the result of a function.  For example, in Pascal functions cannot return records.  In other words, the result type of a function cannot be a Cartesian product type.
 
 

HIGHER-ORDER FUNCTIONS

A function or procedure is called "higher-order" if it takes another function as a parameter. For example, here is one way to compute the dot product of two vectors:
function f(j:int): real;
begin
    return a[j]*b[j];
end;

function sum (lo,hi:int; f: int->real): real;
    var s: real := 0;
begin
    for k := lo to hi do s := s + f(k);
    return s;
end;

The word "signature" means the same as "type". The signature of f here is int -> real and the signature of sum is int * int * (int -> real) -> real.  Remember that the symbol * inside a signature means Cartesian product, i.e. a record type.
 
 

ANOTHER EXAMPLE OF A HIGHER-ORDER FUNCTION

Here are two alternative cosine functions:
function cosine (x: real): real;
begin
    return sine(x + pi/2.0);
end;

function cosine (x: real): real;
    const epsilon = 1e-9;
begin
    return integrate(sine,0,x,epsilon);
end;

Each function implements the cosine function in a very different way, but for the same argument, both always yield similar results.

The signature of integrate is (real -> real) * real * real * real -> real.

Two functions with different implementations can have the same semantics, i.e. specification.  The specification of a function is a mathematical mapping. Its implementation may be something different and more complicated that involves computation.
 
 

PURE VERSUS IMPURE FUNCTIONS

In mathematics, a function in A -> B is a set of ordered pairs where

(1) the first item in each pair is from A and the second item is from B
(2) for each item x in A, there is a unique y in B such that the pair <x,y> is in the mapping.

In programming, a function that satisfies this definition is called pure.  Programming functions can be impure for any or all of several reasons:

One major difference between PLs is exactly what kinds of impure functions are allowed.

Note that the implementation of a function may use one or more of the sources of impurity just mentioned, but this impurity may be encapsulated (i.e. hidden from users of the function) and therefore the function remains pure from a mathematical perspective.
 

 


Copyright (c) by Charles Elkan, 1999.