Session VII: Subprogram
In this Session VII : Subprogram, there are 11 sub topics :
- Introduction
- Fundamentals of Subprograms
- Local Referencing Environments
- Parameter-Passing Methods
- Parameters That Are Subprograms
- Calling Subprograms Indirectly
- Overloaded Subprograms
- Generic Subprograms
- User-Defined Overloaded Operators
- Closures
- Coroutines
Introduction
Two fundamental abstraction facilities can be included in a programming language: process abstraction and data abstraction. In the early history of highlevel programming languages, only process abstraction was included. Process abstraction, in the form of subprograms, has been a central concept in all programming languages.
The first programmable computer, Babbage’s Analytical Engine, built in the 1840s, had the capability of reusing collections of instruction cards at several different places in a program. In a modern programming language, such a collection of statements is written as a subprogram. This reuse results in several different kinds of savings, primarily memory space and coding time. Such reuse is also an abstraction, for the details of the subprogram’s computation are replaced in a program by a statement that calls the subprogram. Instead of describing how some computation is to be done in a program, that description (the collection of statements in the subprogram) is enacted by a call statement, effectively abstracting away the details. This increases the readability of a program by emphasizing its logical structure while hiding the low-level details.
Fundamentals of Subprograms
Each subprogram has a single entry point. The calling program unit is suspended during the execution of the called subprogram, which implies that there is only one subprogram in execution at any given time, control always returns to the caller when the subprogram execution terminates.
A subprogram definition describes the interface to and the actions of the subprogram abstraction. A subprogram call is the explicit request that a specific subprogram be executed. A subprogram is said to be active if, after having been called, it has begun execution but has not yet completed that execution. A subprogram header, which is the first part of the definition, serves several purposes. First, it specifies that the following syntactic unit is a subprogram definition of some particular kind.1 In languages that have more than one kind of subprogram, the kind of the subprogram is usually specified with a special word. Second, if the subprogram is not anonymous, the header provides a name for the subprogram. Third, it may optionally specify a list of parameters.
Local Referencing Environments
Subprograms can define their own variables, thereby defining local referencing environments. Variables that are defined inside subprograms are called local variables, because their scope is usually the body of the subprogram in which they are defined.
Local variables can be stack-dynamic
- Advantages
- Support for recursion
- Storage for locals is shared among some subprograms
- Disadvantages
- Allocation/de-allocation, initialization time
- Indirect addressing
- Subprograms cannot be history sensitive
- Local variables can be static
- Advantages and disadvantages are the opposite of those for stack-dynamic local variables
Parameter-Passing Methods
Semantics Models of Parameter Passing
Parameter-passing methods are the ways in which parameters are transmitted to and/or from called subprograms. First, we focus on the different semantics models of parameter-passing methods. Then, we discuss the various implementation models invented by language designers for these semantics models. Next, we survey the design choices of several languages and discuss the actual methods used to implement the implementation models. Finally, we consider the design considerations that face a language designer in choosing among the methods. Formal parameters are characterized by one of three distinct semantics models: (1) They can receive data from the corresponding actual parameter; (2) they can transmit data to the actual parameter; or (3) they can do both. These models are called in mode, out mode, and inout mode.
Implementation Models of Parameter Passing
A variety of models have been developed by language designers to guide the implementation of the three basic parameter transmission modes.
- Two important considerations
–Efficiency
–One-way or two-way data transfer
- But the above considerations are in conflict
–Good programming suggest limited access to variables, which means one-way whenever possible
–But pass-by-reference is more efficient to pass structures of significant size
Parameters That Are Subprograms
In programming, a number of situations occur that are most conveniently handled if subprogram names can be sent as parameters to other subprograms. One common example of these occurs when a subprogram must sample some mathematical function. For example, a subprogram that does numerical integration estimates the area under the graph of a function by sampling the function at a number of different points.
When such a subprogram is written, it should be usable for any given function; it should not need to be rewritten for every function that must be integrated. It is therefore natural that the name of a program function that evaluates the mathematical function to be integrated be sent to the integrating subprogram as a parameter. Although the idea is natural and seemingly simple, the details of how it works can be confusing. If only the transmission of the subprogram code was necessary, it could be done by passing a single pointer. However, two complications arise. First, there is the matter of type checking the parameters of the activations of the subprogram that was passed as a parameter.
In C and C++, functions cannot be passed as parameters, but pointers to functions can. The type of a pointer to a function includes the function’s protocol. Because the protocol includes all parameter types, such parameters can be completely type checked.
Fortran 95+ has a mechanism for providing types of parameters for subprograms that are passed as parameters, and they must be checked. The second complication with parameters that are subprograms appears only with languages that allow nested subprograms. The issue is what referencing environment for executing the passed subprogram should be used. There are three choices:
- The environment of the call statement that enacts the passed subprogram (shallow binding)
- The environment of the definition of the passed subprogram (deep binding)
- The environment of the call statement that passed the subprogram as an actual parameter (ad hoc binding)
Calling Subprograms Indirectly
There are situations in which subprograms must be called indirectly. These most often occur when the specific subprogram to be called is not known until run time. The call to the subprogram is made through a pointer or reference to the subprogram, which has been set during execution before the call is made. The two most common applications of indirect subprogram calls are for event handling in graphical user interfaces, which are now part of nearly all Web applications, as well as many non-Web applications, and for callbacks, in which a subprogram is called and instructed to notify the caller when the called subprogram has completed its work.
The concept of calling subprograms indirectly is not a recently developed concept. C and C++ allow a program to define a pointer to a function, through which the function can be called. In C++, pointers to functions are typed according to the return type and parameter types of the function, so that such a pointer can point only at functions with one particular protocol.
Overloaded Subprograms
An overloaded operator is one that has multiple meanings. The meaning of a particular instance of an overloaded operator is determined by the types of its operands. For example, if the * operator has two floating-point operands in a Java program, it specifies floating-point multiplication. But if the same operator has two integer operands, it specifies integer multiplication.
An overloaded subprogram is a subprogram that has the same name as another subprogram in the same referencing environment. Every version of an overloaded subprogram must have a unique protocol; that is, it must be different from the others in the number, order, or types of its parameters, and possibly in its return type if it is a function. The meaning of a call to an overloaded subprogram is determined by the actual parameter list (and/or possibly the type of the returned value, in the case of a function). Although it is not necessary, overloaded subprograms usually implement the same process.
C++, Java, C#, and Ada include predefined overloaded subprograms. In Ada, the return type of an overloaded function can be used to disambiguate calls (thus two overloaded functions can have the same parameters). Ada, Java, C++, and C# allow users to write multiple versions of subprograms with the same name
Generic Subprograms
Software reuse can be an important contributor to software productivity. One way to increase the reusability of software is to lessen the need to create different subprograms that implement the same algorithm on different types of data. programs to sort four arrays that differ only in element type.
A polymorphic subprogram takes parameters of different types on different activations. Overloaded subprograms provide a particular kind of polymorphism called ad hoc polymorphism. Overloaded subprograms need not behave similarly. Languages that support object-oriented programming usually support subtype polymorphism. Subtype polymorphism means that a variable of type T can access any object of type T or any type derived from T.
A more general kind of polymorphism is provided by the methods of Python and Ruby. Recall that variables in these languages do not have types, so formal parameters do not have types. Therefore, a method will work for any type of actual parameter, as long as the operators used on the formal parameters in the method are defined.
A generic or polymorphic subprogram takes parameters of different types on different activations, overloaded subprograms provide ad hoc polymorphism. Subtype polymorphism means that a variable of type T can access any object of type T or any type derived from T (OOP languages). A subprogram that takes a generic parameter that is used in a type expression that describes the type of the parameters of the subprogram provides parametric polymorphism
User-Defined Overloaded Operators
Operators can be overloaded by the user in Ada, C++, Python, and Ruby. Suppose
that a Python class is developed to support complex numbers and arithmetic
operations on them. A complex number can be represented with two floatingpoint
values. The Complex class would have members for these two named
real and imag.
A Python example
def __add__ (self, second) :
return Complex(self.real + second.real,
self.imag + second.imag)
Use: To compute x + y, x.__add__(y)
Closures
Defining a closure is a simple matter; a closure is a subprogram and the referencing environment where it was defined. The referencing environment is needed if the subprogram can be called from any arbitrary place in the program. Explaining a closure is not so simple.
If a static-scoped programming language does not allow nested subprograms, closures are not useful, so such languages do not support them. All of the variables in the referencing environment of a subprogram in such a language (its local variables and the global variables) are accessible, regardless of the place in the program where the subprogram is called.
When subprograms can be nested, in addition to locals and globals, the referencing environment of a subprogram can include variables defined in all enclosing subprograms. However, this is not an issue if the subprogram can be called only in places where all of the enclosing scopes are active and visible. It becomes an issue if a subprogram can be called elsewhere. This can happen if the subprogram can be passed as a parameter or assigned to a variable, thereby allowing it to be called from virtually anywhere in the program.
The referencing environment is needed if the subprogram can be called from any arbitrary place in the program, a static-scoped language that does not permit nested subprograms doesn’t need closures. Closures are only needed if a subprogram can access variables in nesting scopes and it can be called from anywhere. To support closures, an implementation may need to provide unlimited extent to some variables (because a subprogram may access a nonlocal variable that is normally no longer alive)
Coroutines
A coroutine is a special kind of subprogram. Rather than the master-slave relationship between a caller and a called subprogram that exists with conventional subprograms, caller and called coroutines are more equitable. In fact, the coroutine control mechanism is often called the symmetric unit control model.
Coroutines can have multiple entry points, which are controlled by the coroutines themselves. They also have the means to maintain their status between activations. This means that coroutines must be history sensitive and thus have static local variables. Secondary executions of a coroutine often begin at points other than its beginning. Because of this, the invocation of a coroutine is called a resume rather than a call.
No Comments »
RSS feed for comments on this post. TrackBack URL