{Assignment Four: Control Structures}
Assigned: Wednesday, March 4, 1998
Due: 11am, Friday, March 13, 1998
1. Parameter Passing
Devise a function, callby() in a generic imperative language
that determines which calling strategy the language uses and returns a
string corresponding to the calling strategy. You should feel free to use
variables and helper functions.
It is likely that your function will have a structure like the following
(which determines whether something is call-by-value).
function callby returns String
begin
// Variable declarations
int x = 3;
// Call a function, affecting some but not all of the variables
helper(x);
// Determine the type of calling strategy by the effect on the
// variable.
if (x == 4) then
return "call-by-value";
else if ... then
...
else
return "call-by-???";
end if
end callby
function helper(int param) returns nothing
begin
param = 4;
end
2. Guarded Control
Often, we learn of a structure in one language that we'd like to use in
another language. Some of us find the nondeterminism of guarded conditionals
interesting, and might want to use it in our favorite languages.
Show how one might simulate guarded conditionals in a language of your choice.
That is, come up with generic code that has the same effect as a guarded
conditional. The structure should permit a number of guard/statement pairs
(represented as you deem best) and execute some statement (not always the
first) with a true guard.
You may make reasonable modifications to the semantics of guarded conditionals.
For example, you don't need to have the program crash and burn if none of
the guards hold. You may also choose whether or not all guards are evaluated.
In all cases, you should make it clear what you decide.
3. GOTO Considered Essential
[This problem is modified from problem 12 on pp. 240-241 of Louden's
Programming Languages: Principles and Practice.]
Dan has suggested that "all these control structures are a way for
mathematicians to restrict what we programmers know how to do"
(paraphrased and made somewhat more extreme). Others clearly feel
the same way.
In responding to the original "GOTO considered harmful"
article, a researcher named Rubin suggested the following code as a
motivation for using GOTO.
for i := 1 to n do begin
for j := 1 to n do
if x[i,j] <> 0 then goto REJECT;
write("First all-zero row is: ',i);
break;
REJECT:
end;
* What do you think this code is supposed to do?
* Rewrite this code using Pascal while loops.
* Compare your code to Rubin's. What are the advantages of each?
* Are there other modern control structures we could use to provide a
similar or better solution?
4. Confusing Assignments
Substitute expressions for alpha and beta in the
following so that the code will print Aagh. Neither of
your expressions should have side-effects (except for the standard
assignment statement side-effect of assigning to the l-value of the
left-hand-side).
alpha = beta; if (alpha != beta) then print "Aagh"; end5. Iterative Merge Sort The traditional merge sort algorithm has the following form:
function mergeSort(Vector v) returns Vector begin // The empty vector is sorted if (v.length == 0) then return v; // A vector of size 1 is sorted if (v.length == 1) then return v; // Split the vector in half mid = v.length / 2; // Sort the two halves first = sort(v.subVector(0,mid)); second = sort(v.subVector(mid+1,last)); // And merge them together return merge(first,second); endAn opponent of recursive algorithms might complain that this is a doubly-inefficient use of memory, as we're using extra memory for the merges and for the recursive calls. In the language of your choice, rewrite this function so that it does no recursive calls, but still follows the same basic method of sorting (merging sorted subvectors to produce larger sorted subvectors). Turn in an appropriate example to demonstrate that it works correctly. 6. Initializations and Declarations [Taken from the notes of John Stone.] Some programming languages require initializations to accompany variable declarations. Summarize the principal arguments for and against such a requirement. Extra Credit: Iterative Quicksort For many algorithms that involve repetition, there is a straightforward translation between the imperative and recursive versions of the algorithm. However, this is not always the case. Consider the famous quicksort algorithm, which is traditionally expressed as: * Pick a pivot. * Divide your list into two halves, one less than or equal to the pivot, the other greater than the pivot. * Sort both halves separately. * Concatenate the two lists. Rewrite this algorithm in the language of your choice so that it has no recursive calls. You will, of course, need to fill in more details.