CS 330 Home Schedule Resources

Assignment 12
State and abstract types.

Estimated time: 4 hours

Acceptance tests for assignment 12.

Grading rubric (i.e. point values) for problems.

Objectives:Learn how to use cells . Understand the difference that it makes to add cells to the declarative model.

Exercises

  1. Introduction to cells. The code below creates two cells and carries out operations to modify their contents. Indicate what the content of each cell is after each instruction (1, 2, and 3).

       declare
       C1={NewCell 0}   C2={NewCell 42}
    
       C1:=@C1+1   (1)
       C2:=@C1+1   (2)
       C1:=@C2+1   (3)
    Also indicate the contents after each of these two instructions. Is the second instruction (2) valid? If so, what does it do and what does it return? If not, explain why.
       declare
       C1={NewCell 0}   C2={NewCell 42}
    
       C1:=@C2   (1)
       C2:=C1    (2)

  2. Instrumenting Fibonacci. We want to compare the effectiveness of two possible implementations of the function Fibonacci.

        % Implementation 1
    fun {Fibonacci1 N}
    if N=<1 then 1 else {Fibonacci1 N-1}+{Fibonacci1 N-2} end
    end

    % Implementation 2
    fun {Fibonacci2 N}
    fun {Fibo I A B}
    if I>=N then B else {Fibo I+1 B A+B} end
    end
    in
    {Fibo 1 1 1}
    end
    Modify the code: use a cell to count the number of recursive calls carried out in each case. The cell should not have any effect on the return value of the calls to Fibonacci.

    Then, explain how to write test programs to compare the functions. (You don't need to actually write code as long as your explanation is sufficiently specific, but you may include code in your explanation if you wish.)

  3. Accumulators and state. To implement effective functions in the declarative paradigm, we used accumulators as the parameters of functions. An accumulator is an implicit form of state. A typical example is the function Reverse which returns the list passed in as an argument with its elements in the opposite order.

       fun {Reverse Xs}
    fun {ReverseAux Xs Ys}
    case Xs of nil then Ys
    [] X|Xr then {ReverseAux Xr X|Ys}
    end

    end
    in
    {ReverseAux Xs nil}
    end
    Rewrite this function to use explicit state in place of the argument Ys of ReverseAux. In other words, build an implementation of the function which uses a cell. You can use a for loop 
         for X in Xs do instruction end
    which is equivalent to
          {ForAll Xs proc {$ X} instruction end}
    The control abstraction  ForAll calls a procedure P on each element in turn of the list Xs. It is defined by
        proc {ForAll Xs P}
    case Xs of nil then skip
    [] X|Xr then {P X} {ForAll Xr P}
    end
    end

  4. A computer. In this exercise, we will implement a computer using postfix notation  (or reversed Polish notation ). In this notation, the operator is written after its two operands. For example, the expression "(13+45)*(89-17)" is written "13 45 + 89 17 - *". The advantage of this notation is that it does not require the use of parentheses.

    The evaluation of a postfix expression is very simple. One uses a stack to store the intermediate results. It is enough to traverse the expression from left to right and to treat the elements (values and operators) one by one. When a value is read, you push it on the stack. When an operator is read, you pop two values off the top of the stack, apply the operator to them, then push the result on the stack. At the end, the stack must contain only one value: the result of the calculation. From left to right below are the stages of the calculation of the postfix expression  "13 45 + 89 17 - *". The upper row contains the remainder of the expression, the lower row shows the stack of intermediate values.

    13 45 + 89 17 - * 45 + 89 17 - * + 89 17 - * 89 17 - * 17 - * - * *

    13 45
    13
    58 89
    58
    17
    89
    58
    72
    58
    4176

    Write an abstraction of a data stack with explicit state. This abstraction is defined by four operations: NewStack, IsEmpty, Push, and Pop. Push is a procedure, the others are functions.

    A stack is represented by a cell containing a list. The list contains the elements of the stack, from top to bottom. The first element of the list is thus the top of the stack.

    Then, write a function Eval which takes as a parameter a postfix expression and returns its value. The expression is represented by a list whose each element is either an integer, or one of the constants '+' '-' '*' and '/', the latter representing integer division. The expression in the example above will be represented by the list [13 45 '+' 89 17 '-' '*']. The function Eval traverses this list and updates the contents of the stack, while following the algorithm presented informally above.

       {Browse {Eval [13 45 '+' 89 17 '-' '*']}}   % Displays 4176 = (13+45)*(89-17)
    {Browse {Eval [13 45 '+' 89 '*' 17 '-']}} % Displays 5145 = ((13+45)*89)-17
    {Browse {Eval [13 45 89 17 '-' '+' '*']}} % Displays 1521 = 13*(45+(89-17))

  5. Encapsulation of the stack state. We now will implement an alternative of the stack abstraction presented in the preceding exercise. This alternative renders the state of the stack invisible to the user. It is thus a matter of ``hiding'' the cell containing the list via lexical scoping. The function NewStack2 will not return the cell directly. It rather will return a list of functions and procedures:

       {NewStack2} -> [IsEmpty Push Pop]
    Functions IsEmpty, Pop, and procedure Push are specific to the stack which has just been created. Here is an example of their use, with two stacks.
       declare

    [IsEmpty1 Push1 Pop1]={NewStack} % stack 1
    [IsEmpty2 Push2 Pop2]={NewStack} % stack 2

    {Browse {IsEmpty1}} % displays true; the stack is empty
    {Push1 13} % push 13 onto stack 1

    {Browse {IsEmpty1}} % displays false; stack 1 contains 13
    {Browse {IsEmpty2}} % displays true; stack 2 is empty
    {Push1 45} % push 45 onto stack 1
    {Push2 {Pop1}} % pop 45 off of stack 1 and push it onto stack 2
    {Browse {IsEmpty2}} % displays false; stack 2 contains 45

    {Browse {Pop1}} % pops 13 off the stack and displays it
    Here is a skeletal implementation for NewStack2. Complete it.
       fun {NewStack2}
    ...
    fun {IsEmpty} ... end
    proc {Push X} ... end
    fun {Pop} ... end
    in
    [IsEmpty Push Pop]
    end

    Adapt the function Eval that you wrote in the preceding exercise so that it uses this implementation of the stack data abstraction. Name the new function Eval2.

  6. Parameter passing . The purpose of this exercise is to understand the effects of different parameter passing mechanisms. Assume that the code below is pseudocode (not OZ!!) that executes properly for all five parameter-passing mechanisms discussed in class: call-by-value, call-by-reference, call-by-value-result, call-by-name, call-by-need. Assume that all variables are mutable, and that '=' performs assignment. Tell what result would be Browsed at the end of execution under each kind of parameter passing mechanism. Show your reasoning.
    declare A=2 B=4 C=1
    proc {P X Y Z}
      C=5
      X=Z
      C=4
      Y=Z+A
    end
    in {P A B A+C}
    {Browse B}
    

  7. Feedback.
    Scale
    1. Not at all
    2. Not very
    3. Slightly
    4. Somewhat
    5. Mostly
    6. Very
    7. Extremely