CS 331 Spring 2025  >  Exam Review Problems, Set D


CS 331 Spring 2025
Exam Review Problems, Set D

This is the fourth set of exam review problems.

Problems

Review problems are given below. Answers are in the Answers section of this document. Do not turn these in.

    1. What is overloading?
    2. Give an example of a kind of overloading that cannot be done in C++ but can be done in one of the PLs we studied.
    1. What do we mean by scope?
    2. What kind of thing has a scope?
    3. Write some code. Name something in the code, and indicate what its scope is.
    1. What is an expression?
    2. What is the type of the following Lua expression?
      1+2
    1. What is a literal?
    2. Give an example of a literal. Give the literal itself, its type, and the name of the programming language.
    1. What is meant by binding and bound?
    2. What do we call something that is not bound?
    3. In one of the PLs we studied, we can check whether something is bound. Explain.
    1. What is a thunk?
    2. We looked at a context in which thunks are used. Explain.
    1. What is reflection?
    2. We studied a programming language that is known for its excellent support for reflection. What is the primary feature in the programming language that is used for reflection?
    1. Scheme is based on a another programming language, which is called what?
    2. What is the main philosophical idea that initially set Scheme apart from the programming language it was based on?
  1. Describe Scheme’s type system.
    1. Static or dynamic?
    2. Mostly manifest or mostly implicit?
    3. Fixed set of types or extensible?
    4. Types apply to variables?
  2. What does each of the following mean in Scheme?
    1. #t
    2. #\b
    3. "x"
    4. 1/2
    5. ;ab
    1. What keyword—if any—introduces a Scheme function?
    2. True or false: Scheme has first-class functions.
    3. Scheme has first-class identifiers. What are these called?
    4. True or false: Scheme allows for lambda functions.
    5. True or false: By default, Scheme does lazy evaluation.
    6. How can the other kind of evaluation—the one that is not the default—be done in Scheme?
    1. What is a Scheme atom?
    2. List all non-atom Scheme types.
  3. What syntax does Scheme use for binary operators?
    1. We covered two Scheme conditional flow-of-control constructs. Name and describe them.
    2. Which Scheme values are truthy, and which are falsy?
    1. What is a single quote used for in Scheme?
    2. A single quote is an abbreviation for something longer in Scheme. Explain.
    1. Names of Scheme predicates commonly end in what?
    2. Give an example of a standard Scheme predicate whose name ends as above. Explain what this predicate does.
    1. How is a list normally evaluated in Scheme?
    2. The normal list evaluation rule has an important exception. Explain.
    1. What does eval do in Scheme?
    2. eval does its work twice. Explain.
    1. Describe a construction that defines local variables in Scheme.
    2. What happens if we insert a symbol as the first argument in the above construction.
    1. What do Scheme car and cdr do when given lists?
    2. What do Scheme car and cdr do more generally?

Answers

    1. Overloading happens when a single name in a single namespace refers to multiple entities.
    2. Here are two examples.
      • In Haskell, operators other than ones defined in the standard can be overloaded. In C++, only standard operators can be overloaded.
      • Also in Haskell, functions can be overloaded on their return types. That is, we can write two functions that have the same name and the same parameter types, but which differ in their return types. In C++, functions can be overloaded only on the number, types, and passing methods of their parameters.
    1. The scope of an identifier is the code from which the identifier is accessible.
    2. An identifier has a scope.
    3. Here is a Lua function definition.
        function ff()
            local n
            n = 42
            return n
        end
      In the above code, the scope of the identifier n is the body of the function, that is, the three indented lines between “function ff()” and “end”.
    1. An expression is an entity that has a value.
    2. In Lua, the expression “1+2” has type number.
    1. A literal is a representation of a fixed value in source code. The value itself is represented, not an identifier bound to the value, and not a computation whose result is the value.
    2. Many examples are possible. Here are several.
      • "abc" is a Lua literal of type string. (It is also a Haskell literal of type String.)
      • [[abc]] is a Lua literal of type string.
      • 42 is a Lua literal of type number. (It is also a C++ literal of type int.)
      • #t is a Scheme literal of Boolean type.
    1. Binding is associating a variable with a value. Once this is done, the variable is said to be bound.
    2. A variable that is not bound is said to be free.
    3. In Prolog, we can check whether a variable is bound using the predicates var/1 and nonvar/1. When passed a bound variable, the former fails, while the latter succeeds. When passed a free variable, the reverse happens.
    1. A thunk is a reference to code whose execution computes a value.
    2. In Haskell, the implementation of lazy evaluation typically involves thunks. A thunk is used as a placeholder for a value that has not been computed yet. When the value is needed, the code referenced by the thunk is called, and the thunk is replaced by the resulting value.
    1. Reflection is the ability of a computer program to deal with its own code: examining the code, looking at its properties, possibly modifying it, and executing the modified code.
    2. The Scheme programming language offers excellent support for reflection. It does this primarily with macros.
    1. Scheme is based on the programming language Lisp.
    2. What sets Scheme apart from most List implementations is its minimalist design philosophy.
    1. Scheme has dynamic typing.
    2. Scheme’s typing is implicit.
    3. Scheme has a fixed set of types.
    4. Scheme types do not apply to variables; only values have types.
    1. #t. This is the Boolean true literal.
    2. #\b. This is the 'b' character literal.
    3. "x". This is a string of length 1 holding the 'x' character.
    4. 1/2. This is an exact rational number literal with value 1/2.
    5. ;ab. This is a comment.
    1. A Scheme function (that is, procedure) definition is generally introduced by define or lambda. However, these are not keywords in Scheme.
    2. True. Scheme has first-class functions.
    3. Scheme’s first-class identifiers are called symbols.
    4. True. Scheme allows for lambda functions.
    5. False. By default, Scheme does eager evaluation.
    6. Lazy evaluation can be done in Scheme using promises. A promise is created with the macro delay. It is evaluated using the procedure force.
    1. A Scheme atom is a single value that does not involve any of the constructs used to form lists.
    2. Scheme has two non-atom types: pair and null.
  1. Scheme has no special syntax for binary operators. The ordinary syntax for procedure calls is used. For example, to check whether two numbers a and b are equal, we would do “(= a b)”.
    1. We covered two Scheme conditional flow-of-control constructs. One is macro if, which takes a condition and two expressions. If the condition is truthy, then It evaluates and returns the first expression; otherwise it evaluates and returns the second expression. The second is macro cond, which takes one or more two-item lists, each containing a condition and an expression. It evaluates the conditions in order, stopping when one is truthy, and then evaluating and returning the corresponding expression. The last condition may be replaced by else, which counts as truthy.
    2. In Scheme, #f (Boolean false) is falsy. All other values are truthy.
    1. In Scheme, a single quote suppresses evaluation.
    2. A single quote is an abbreviation for a two-item list beginning with quote. For example, “'abc” is an abbreviation of “(quote abc)”.
    1. Names of Scheme predicates commonly end in a question mark (?).
    2. One example is the predicate number?. This takes one argument and returns #t (Boolean true) if the argument is of a number type. (Many other answers are possible, such as Scheme type-checking predicates like null?, promise?, and others, along with other standard predicates: list?, even?, etc.)
    1. The normal way for Scheme to evaluate a list is, first, to evaluate each list item, and, second, to call the value of the first item as a procedure, with the values of the other items as its arguments.
    2. The exception to the normal list evaluation rule is when the first item is a macro. In this case, the other items are passed to it unevaluated.
    1. Scheme eval evaluates the expression passed to it.
    2. eval does its work twice, because it is a procedure. First, the argument is evaluated as part of the normal evaluation rule for lists. Then eval is called, and the result is evaluated again.
    1. We can use local variables in Scheme with the macro let (and its variants, like let*). This takes a list of two-item lists and an expression. Each two item list is a symbol and an expression. Each symbol is set to the value of its expression—thus binding a local variable—and then the expression is evaluated with each symbol having its value.
    2. If we insert a symbol as the first argument in a let, then that symbol becomes the name of a local procedure. Calling this procedure restarts the let; the values of the various local variables are arguments.
    1. When given a nonempty list, Scheme car returns its first item. cdr returns a list of all the other items.
    2. Scheme car and cdr each take a pair. car returns its first item (“left child pointer”), while cdr returns its second item (“right child pointer”).