| CS 330 | Home | Schedule | Resources |
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.
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)
Instrumenting Fibonacci. We want to compare the effectiveness
of two possible implementations of the function Fibonacci.
% Implementation 1Modify 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
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
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.)
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 endwhich 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
In your opinion, is your cell-based function efficient compared with accumulator version above?
Is the explicit state that you introduced visible or encapsulated? If it is encapsulated, at which scope? How many times do you create a cell?
Can you also create an explicit state for the argument Xs?
If so, implement it. If not, explain why.
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 |
58 |
89 |
17 |
72 |
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.
{ NewStack } returns a new stack.{ IsEmpty S } returns true
if the stack S passed in as an argument is empty,
false if not.{ Push S X } pushes the element X on
the top of stack S.{ Pop S } removes the top of the stack S
and returns it.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))
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.
declareHere is a skeletal implementation for
[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
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.
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}