**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"; end

**5. 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); end

An 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.

**Disclaimer** Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.

Source text last modified Mon Mar 9 16:32:11 1998.

This page generated on Mon Mar 9 16:35:20 1998 by SiteWeaver.

Contact our webmaster at rebelsky@math.grin.edu