CS 331 Spring 2009  >  Additional Lecture Notes for Monday, March 23, 2009

CS 331 Spring 2009
Additional Lecture Notes for Monday, March 23, 2009

Names in Programming Languages (cont’d)

Concerning Strong Typing

The text says that a language is strongly typed if type errors are always detected.

This is a fine definition. However, I would like to point out that the term “strongly typed” is often used in a relative sense. That is, when we say a language is strongly typed, we often mean, not that type errors are always detected, but that type errors are detected relatively often, perhaps contrasted with some other language in which they are detected less often.

Concerning Type Compatibility

The text (also chapter 5 slides 23–29) mentions name type compatibility (essentially what C++ uses when checking parameter types for non-template functions) and structure type compatibility (not used in C++).

There is also duck typing. This takes its name from the saying.

If it looks like a duck, walks like a duck, and quacks like a duck, then it must be a duck.

(Or something like that.)

The idea is that a compatible type is one that has the same operations. This is essentially what C++ does in the context of templates.

For example, consider the following code.

template <typename T>
T dubl(T n)
{
    return n + n;
}

This function can be called with a parameter of a given type, as long as that type has the required operations: binary operator+ and a copy constructor.

Haskell’s type compatibility rules are an explicit version of duck typing. That is, a type is compatible if it has the right operations. However, in order to give it those operations, you must explicitly declare it to be in the right type class. For example, if a function applies only the == operator to its parameters, then it can take any type that has that operator. However, in order to define that operator for a type, you must place the type in class Eq.

Concerning Dynamic Scope

In a language with dynamic scope, we consider the history of the program when determining whether a variable is accessible. C and C++ do not have dynamic scope.

Now, consider: why do C and C++ not allow local functions? For example, the following is not legal in either language.

void foo()
{
    int x;

    void bar()  // ERROR; local functions not allowed
    { ++x; }

    // More code here
}

This looks reasonable; why is it not allowed? Well, suppose function foo were recursive. Then there might be many versions of variable x on the stack. Pretty clearly, function bar would access the most recently created one. Now, what if function bar were also recursive. How would it find the proper copy of x? It would have to search back through the stack frames to find the right one. This kind of accidental slow behavior is the sort of thing that C is designed to avoid. Thus, no dynamic scoping, and so no local functions.

Note that, strictly speaking, in C++ we can define a function inside a function, by putting a function inside a class inside another function. However, the inner function cannot access the outer function’s automatic local variables.

void foo()
{
    int x;
    static int y;

    class MyClass {
    public:
        void bar()
        {
            ++x;  // ERROR; x is automatic
            ++y;  // This is legal, however.
        }
    };

    // More code here
}

Concerning the Referencing Environment

The referencing environment of a statement consists of the values of all variables accessible when the statement is executed. In some languages, we can grab the referencing environment and keep it around. This is called a closure. Here is an example of the use of a closure in Python.

def adder(x):
    def addx(y);
        return x + y;
    return addx  # Returns a closure
                 #  which keeps track of the variable x in the
                 #  referencing environment, even though x is
                 #  local to function adder, and thus goes away

add5 = adder(5)  # Creates a function that adds 5 to its param
add3 = adder(3)  # Creates a function that adds 3 to its param

print(add5(10))  # Outputs 15
print(add3(10))  # Outputs 13
print(add5(1))   # Outputs 6
print(add3(1))   # Outputs 4


CS 331 Spring 2009: Additional Lecture Notes for Monday, March 23, 2009 / Updated: 23 Mar 2009 / Glenn G. Chappell / ffggc@uaf.edu Valid HTML 4.01!