1.12k likes | 1.13k Views
This chapter discusses the evaluation of variables and constants in programming languages, including their order of evaluation, side effects, and potential dangers of operator overloading. It also covers the concept of short-circuit evaluation in boolean expressions.
E N D
CE2004 Principles of Programming Languages Chapter 7 Expressions and Assignment Statements EIGHTH EDITION
Evaluation of Variables and Constants • Variables in expressions are evaluated by fetching their values from memory. • Constants are sometimes evaluated the same way. • In other cases, a constant may be part of the machine language instruction and not require a memory fetch.
Evaluation of Parenthesized Expression • If an operand is a parenthesized expression, then all operators it contains must be evaluated before its value can be used as an operand.
Side Effects and Evaluation Order • If neither of the operands of an operator has side effect, then operand evaluation order is irrelevant.
Side Effects • A side effect of a function, called a functional side effect, occurs when the function changes one of its • parameters or • a global variables. • A global variable is declared outside the function but is accessible in the function.
Example – without Side Effects • Consider the expression a + fun (a) • If fun does not have the side effect of changing a, then the order of evaluation of the two operand, a and fun(a), has no effect on the value of the expression.
Example – with Side Effects a + fun (a) • If fun changes a, there is an effect.
Assumption • Consider the following situation: • fun returns 10 and changes the value of its parameter to 20. • Suppose we have the following statements: a = 10; b = a + fun(a);
Different Evaluation Orders Create Different Results • If the value of a is fetched first (in the expression evaluation process), its value is 10 and the value of the expression is 20. • If the second operand is evaluated first, then the value of the first operand is 20 and the value of the expression is 30.
Example int a = 5; int fun1() { a = 17 ; return 3; } /* end of fun1 */ void main() { a = a + fun1(); } /* end of main */ • The value computed for a in main depends on the order of evaluation of the operands in the expression a + fun1(). • The value of a will be • either 8 (if a is evaluated first) or • 20 (if the function call is evaluated first).
Multiple Use of Notations • Arithmetic operators are often used for more than one purpose. • For example, in the imperative programming languages + is used to specify • integer addition and • floating-point addition. • Some languages, java, for example, also use it for string catenation.
Operator Overloading • The multiple use of an operator is called operator overloading. • Operator overloading is generally thought to be acceptable, as long as readability and/or reliability do not suffer.
Ampersand (&) in C • As a binary operator, it specifies a bitwise logical AND operation. • As a unary operator with a variable as its operand, the expression value is the address of that variable. • In this case, the ampersand is called the address-of operator.
Possible Dangers of Overloading • There are two problems with the multiple use of the ampersand. • First, using the same symbol for two completely unrelated operations is detrimental to readability. • Second, the simple keying error of leaving out the first operand for a bitwise AND operation can go undetected by the compiler, because it is interpreted as an address-of operator. • Such an error may be difficult to diagnose.
Short-Circuit Evaluation • A short-circuit evaluation of an expression is one in which the result is determined without evaluating all of the operands and/or operators.
Example • For example, • the value of the arithmetic expression (3 * a) * (b / 13 - 1) is independent of the value of (b / 13 - l) if a is 0, because 0 * x = 0 for any x. • So when a is 0, there is no need to evaluate • (b / 13 - l) or • perform the second multiplication. • However, in arithmetic expressions this shortcut is not easily detected during execution, so it is NEVER taken.
Another Example • The value of the Boolean expression (a >= 0) && (b < 10) is independent of the second relational expression if a < 0, because (FALSE && x) is FALSE for all values of x. • So when a < 0, there is no need to evaluate b, the constant 10, the second relational expression, or the && operation. • Unlike the case of arithmetic expressions, this shortcut can be easily discovered during execution and taken.
A Potential Problem with Non-short-Circuit Evaluation of Boolean Expressions • Suppose • suppose we write a table lookup loop using the while statement. • assuming • list, which has listlen elements, is the array to be searched • key is the searched-for value index = 0; while ((index < listlen) && (list[index] <> key)) index = index +1 ; • If evaluation is not short circuit, both relational expressions in the Boolean expression of the while statement are evaluated, regardless of the value of the first. • Thus, if key is not in list, The iteration that has index == listlen will reference list[listlen], which causes the indexing error because list is declared to have listlen-l as an upper bound subscript value.
Short-circuit Evaluation Could Solve the Previous Problem • If a language provides short-circuit valuation of Boolean expressions and it is used, situation in the previous slide is not a problem. • In the preceding example, a short-circuit evaluation scheme would evaluate the first operand of the AND operator, but it would skip the second operand if the first operand is false.
Short-Circuit Evaluation May Result in Errors • Short-circuit evaluation of expressions exposes the problem of allowing side effects in expressions. • Suppose that • short-circuit evaluation is used on an expression and • part of the expression that contains a side effect is not evaluated then the side effect will only occur in complete evaluations of the whole expression. • If program correctness depends on the side effect, short-circuit evaluation can result in a serious error.
Example • Considconsider the C expression (a > b) || (b++ / 3) • In this expression, b is changed (in the second arithmetic expression) only when a<=b. • If the programmer assumed b would be changed every time this expression is evaluated during execution, the program will fail.
CE2004 Principles of Programming Languages Chapter 9 Subprograms EIGHTH EDITION
Chapter 9 Topics • Introduction • Fundamentals of Subprograms • Design Issues for Subprograms • Local Referencing Environments • Parameter-Passing Methods • Parameters That Are Subprogram Names • Overloaded Subprograms • Generic Subprograms • Design Issues for Functions • User-Defined Overloaded Operators • Coroutines
Abstraction Facilities in a Programming Language • Two fundamental abstraction facilities can be included in a programming language: • process abstraction • In the early history of high-level programming languages, only process abstraction was recognized and included. • Process abstraction has been a central concept in all programming languages. • data abstraction • In the 1980s, however, many people began to believe that data abstraction was equally important. • Data abstraction is discussed in detail in Chapter 11.
Properties of Subprograms • All subprograms discussed in this chapter, except the coroutines described in Section 9.11, have the following characteristics; • 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.
Subprogram Definitions • A subprogram definition describes the interface to and the actions of the subprogram abstraction.
Subprogram Call • A subprogram call is the explicit request that the called subprogram be executed.
Active Subprogram • A subprogram is said to be active if, after having been called, it has begun execution but has not yet completed that execution.
Classes of Subprograms • The two fundamental kinds of subprograms, • procedures and • functions, are defined and discussed in Section 9.2.4.
Subprogram Headers • 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. • Some programming languages include two different kinds of subprograms; specifically, procedures and functions. • Second, it provides a name for the subprogram. • Third, it may optionally specify a list of parameters. • They are optional because not all subprogram definitions have parameters.
Header Examples • The following is the header of a Fortran subprogram named Adder. Subroutine Adder(parameters) • In Ada, the header for Adder would be procedure Adder(parameters)
C Function Header • No special word appears in the subprogram header of a Csubprogram. • C has only one kind of subprogram, functions (and/or methods). • The header of a function is recognized by context rather than by a special word. • For example, void adder(parameters) • would serve as the header of a function named adder, where void indicates that it does not return a value.
The Parameter Profile and the Protocol of a Subprogram • The parameter profile (sometimes called the signature) of a subprogram is the • number • order and • types of its formal parameters. • The protocolof a subprogram is its parameter profile plus, if it is a function, its return type.
The Declarations of Variables in C • In Cthe declarations of variables can be used to provide type information but not to define variables. • A variable declaration in C is used only outside function definitions. • A declaration is necessary when a variable must be referenced before the compiler has seen its definition.
Subprogram Declarations • Subprograms can have declarations as well as definitions. • This form parallels the variable declarations and definitions in C. • Subprogram declarations provide the subprogram’s protocol, but do not include their bodies. • They are necessary in languages that do not allow forward references to subprograms.
Declaration and Type Checking • In both the cases of variables and subprograms, declarations are needed for static type checking. • In the case of subprograms, it is the type of the parameters that must be checked.
Usage of Subprogram Declarations • Function declarations are common in C and C++ programs, where they are called prototypes. • In most other languages, subprograms do not need declarations, because there is no requirement that subprograms defined before they are called.
Approaches a Subprogram Could Use to Access Data • Subprograms typically describe computations. • There are two ways that a non-method subprogram can gain access to the data that it is to process: • through direct access to nonlocal variables (declared elsewhere but visible in the subprogram) • through parameter passing.
Data Passing through Parameters • Data passed through parameters are accessed through names that are local to the subprogram. • Parameter passing is more flexible than direct access to nonlocal variables.
Parameterized Computation • In essence, a subprogram with parameter access to the data that it is to process is a parameterized computation. • It can perform its computation on whatever data it receives through its parameters (presuming the types of the parameters are as expected by the subprogram).
Disadvantages of Data Access through Non-local Variables • If data access of a subprogram is through nonlocal variables, the only way the computation can proceed on different data is to assign new value to those nonlocal variables between calls to the subprogram. • Variables that are visible to the subprogram where access is desired often end up also being visible where access to them is not needed (see chapter 5).
Using a Subprogram as a Parameter • In some situations, it is convenient to be able to transmit computations, rather than data, as parameters to subprograms. • In these cases, the name of the subprogram that implements that computation may be used as a parameter.
Formal Parameters • The parameters in the subprogram header are called formal parameters. • They are sometimes thought of as dummy variables because they are not variables in the usual sense: In some cases, they are bound to storage only when the subprogram is called.
Actual Parameters • Subprogram call statements must include • the name of the subprogram • a list of parameters to be bound to the formal parameters of the subprogram. • These parameters are called actual parameters. • They must be distinguished from formal parameters because the two can have different restrictions on their forms, and of course their uses are quite different.
Positional Parameters • In nearly all programming languages, the correspondence between actual and formal parameters—or the binding of actual parameters to formal parameters—is done by simple position: • The first actual parameter is bound to the first formal parameter and so forth. • Such parameters are called positional parameters. • This is an effective and safe method for relatively short parameter lists.
Keyword Parameters • When lists are long, however, it is easy for the programmer to make mistakes in the order of actual parameters in the list. • One solution to this problem is to provide keyword parameters, in which the name of the formal parameter to which an actual parameter is to be bound is specified with the actual parameter.
Advantages of Keyword Parameters • The advantage of keyword parameters is that they can appear in any order in the actual parameter list. • Ada procedures can be called using this method, as in Sumer(Length => My_Length, List => My_Array, Sum => My_Sum); • where the definition of Sumer has the formal parameters Length, List, and Sum.
Disadvantages of Keyword Parameters • The disadvantage to keyword parameters is that the user of the subprogram must know the names of formal parameters.
Combining Keyword Parameters with Positional Parameters • In addition to keyword parameters, Ada and Fortran 90 allow positional parameters. • The two can be mixed in a call, as in Sumer(Length, List => My_Array, Sum => My_Sum); • The only restriction with this is that after a keyword parameter appears in the list, all remaining parameters must be keyworded. This is necessary because position may no longer be well defined after a keyword parameter has appeared.