This preview shows pages 1–3. Sign up to view the full content.
This preview has intentionally blurred sections. Sign up to view the full version.View Full Document
Unformatted text preview: Last Time: * Manifesto: Spend less time writing more correct programs! * Interfaces: the contract between client and implementor * Pre-Conditions: meet them, or behavior is undefined. Outline: * MODIFIES clauses and stacks * Nature of recursion * Recursive functions * Recursion: a problem ++++++++++++++++++++++++++++++++++++++++++++++++++++++ So far, we've been talking about function specification. We've discussed EFFECTS clauses (always present) and REQUIRES clauses (only if the function has pre-conditions) but not yet MODIFIES clauses. A MODIFIES clause identifies any function argument or piece of global state that *might* change if this function is called. One way this can happen is if an argument is passed by-reference, instead of by-value: void swap(int &x, int &y); // MODIFIES: x, y // EFFECTS: exchanges the values of x and y The ampersand (&) means that you get a *reference* to the caller's argument, not a *copy* of it---and with that reference it is possible to change the value of that argument. Note: if the function *could* change a reference argument, it must go in the MODIFIES clause. Leave it out only if the function can *never* change it. ************************************************ Before we get to the next topic, we first have to remind you how function call works, and specifically, how the "call stack" works. When we call a function (using pass-by-value semantics) the program follows these steps: 1: Evaluates the actual arguments to the function. (Note, the order is not guaranteed.) 2: Creates an "activation record" (sometimes called a "stack frame") to hold the function's formal arguments and local variables. 3: Copies the actuals' values to the formals' storage space 4: Evaluates the function in its local scope 5: Replaces the function call with the result. 6: Destroys the activation record. Activation records are typically stored as a *stack*. To understand how this works, think about the stack of clean plates in a typical residence hall cafeteria. When a plate is cleaned, it is put on the top of the stack. When someone needs a plate, they take it from the top of the stack. Cleaning a plate is like calling a function; taking a plate is like returning from that function. Activation records work just like this: when a procedure is called, an activation record for *this* invocation is added to the "top" of the stack. When that procedure returns, it's record is removed from the "top" of the stack. In the meantime, this procedure may have called other functions, (creating corresponding activation records), but they all must have returned (destroyting corresponding activation records) before this procedure can return. I put "top" in quotes, because, by convention, stacks are typically drawn growing *down* rather than *up*....
View Full Document
- Winter '08