70 likes | 94 Views
Functions vs. Procedures. It is useful to differentiate functions vs. procedures Procedures have side effects but usually do not return a value (C++ doesn ’ t follow this strictly) Functions provide a value and usually don ’ t have side effects (again C++ doesn ’ t enforce this)
E N D
Functions vs. Procedures • It is useful to differentiate functions vs. procedures • Procedures have side effects but usually do not return a value (C++ doesn’t follow this strictly) • Functions provide a value and usually don’t have side effects (again C++ doesn’t enforce this) • Procedures (or functions) abstract commonly used combinations of other procedures (or functions) • Especially if the side effect (e.g., printing out a list) or computation (e.g., factorial) is usefully expressed recursively • Whenever a procedure (or function) calls another one, data must be remembered during each such call • Stored in an activation record visible during the interval during which the procedure (or function) is executing
Procedure Definition, Activation, Semantics • Actions taken by a procedure/function form its body • In C++, the statements between the opening { and closing } • Calling sequence (+ prologue + epilogue) sets up calls to it • Also must store actual parameters and local variables • Kept in activation record of the currently running procedure • Temporary variables, return values, etc. also may be there • Side effects may occur with non-local references • E.g., updating a global variable or one passed by reference • Two different environments must be considered • Calling environment (provides values of formal parameters) • Defining environment (provides values of external variables) • In C/C++, only formal parameters can be used to communicate between calling and called environments (!)
Parameter Passing • Pass by value copies (calling to called environment) • In C++, this may call a copy constructor (user defined types) • A different location is used, no side effects of local changes • Pass by reference aliases (same location in both) • Local changes to by-reference parameters → side effects • In C++, can pass pointers by value (copies them) • Local changes to the passed pointer (i.e., changing where it points) do not affect (where) the original pointer (points) • However, the copied pointer and the original pointer point to the same location, so dereferencing either of them gives a reference to the same location (if changed → side effect) • Other variations: pass-by-name, in/out parameters • Support lazy evaluation, type checking direction of updates
Environments, Activation, Allocation • Fully static environments (e.g., Fortran 77) • Activation records all known in advance • Can lay out and link all activation records for all calls • Limited, since recursion, etc. are off-limits in that approach • Stack based run-time environments (e.g., C or C++) • Need a stack on which activation records are pushed / popped (linked / unlinked) as functions are called and return • Need environment pointer (ep) to current activation record • Need instruction pointer (ip) into the code for the procedure • Closure <ep, ip> gives code, resolves non-local references • Fully dynamic run-time environments • Reclaim unreachable activation records (e.g., via reference counting, mark-and-sweep, or generational collection)
Dynamic Memory Management • Languages that make functions/procedures first class require fully dynamic memory management • Stack semantics cannot correctly express all scenarios • Need garbage collection (as well as maintaining free space which is needed even with C malloc/free, C++ new/delete) • When memory is returned to heap, need to coalesce • Adjacent free regions are joined into a larger free region • Compaction (expensive) can reduce (external) fragmentation • Buddy approach (Knuth) allocates blocks sized 2n, trades off internal fragmentation for fast non-fragmenting coalescing • Need to determine when and how to collect garbage • Ref count: eager, simple (expensive?) misses cyclic garbage • Generational mark/sweep cleans up transient garbage
Generics • Implicit parametric polymorphism can enhance reuse • Allows code to be parameterized with incomplete types • Type checking may be deferred until run-time (e.g., in Lisp) • Generics offer an alternative with earlier type checking • Write exemplars (templates in C++) with type parameters • Constraints inferred/checked at compile time instantiation • E.g., T::iterator type for a (container) template parameter T • Can be closely integrated with the language as a result • Instantiation may be explicit or implicit • E.g., vector<int> vs. swap(a, b) in C++
Today’s Studio Exercises • We’ll code up ideas from Scott Chapter 8.1-8.4 • Looking at control abstraction for functions/procedures • Today’s exercises are again in C++ • Please take advantage of the on-line tutorial and reference manual pages that are linked on the course web site • As always, please ask us for help as needed • When done, email answers with subject line “Control Abstraction Studio I” to cse425@seas.wustl.edu