Chapter 8 StatementLevel Control Structures ISBN 0 321
Chapter 8 Statement-Level Control Structures ISBN 0 -321 -49362 -1
Augment Sebesta Material m CSE 4102 m Programming Languages-Cheng (Fall 2004) q http: //www. cse. msu. edu/~cse 452/Fall 2004/Lectures/08 -control-new Edited. pptx Type Systems and Structures- Bermúdez q q https: //www. cise. ufl. edu/class/cop 5556 sp 16/Lecture_20. ppt OV-2
Chapter 8 Topics • • • Introduction Selection Statements Iterative Statements Unconditional Branching Other Selection Statements – https: //www. cise. ufl. edu/class/cop 5556 sp 16/Lecture_20. ppt • Practical PL Level Iteration and Recursion – https: //www. cise. ufl. edu/class/cop 5556 sp 16/Lecture_21. ppt • Guarded Commands • Conclusions Copyright © 2015 Pearson. All rights reserved. 1 -3
Levels of Control Flow – Within expressions (Chapter 7) – Among program units (Chapter 9) – Among program statements (this chapter) Copyright © 2015 Pearson. All rights reserved. 1 -4
Control Statements: Evolution • FORTRAN I control statements were based directly on IBM 704 hardware • Much research and argument in the 1960 s about the issue – One important result: It was proven that all algorithms represented by flowcharts can be coded with only two-way selection and pretest logical loops Copyright © 2015 Pearson. All rights reserved. 1 -5
Control Structure • A control structure is a control statement and the statements whose execution it controls • Design question – Should a control structure have multiple entries? Copyright © 2015 Pearson. All rights reserved. 1 -6
Selection Statements • A selection statement provides the means of choosing between two or more paths of execution • Three general categories: – One-way selection statements – Two-way selectors statements – Multiple-way selectors statements • Nested selection statements? Copyright © 2015 Pearson. All rights reserved. 1 -7
Selection Statements u Very Early One-Way Examples FORTRAN IF: IF (boolean_expr) statement u Limitation: l Can select only a single statement; to select more, a GOTO must be used, as in the following example IF (. NOT. condition) GOTO 20 . . . 20 CONTINUE Organization of Programming Languages-Cheng (Fall 2004) 8
Two-Way Selection Statements • General form: if control_expression then clause else clause • Clause can be single statements or compound statements • Control_expression • – arithmetic/Boolean expressions Design Issues: – – – What is form and type of control expression? How are then and else clauses specified? How should the meaning of nested selectors be specified? Copyright © 2015 Pearson. All rights reserved. 1 -9
The Control Expression • If then reserved word or some other syntactic marker is not used to introduce then clause, the control expression is placed in parentheses • In C 89, C 99, Python, and C++, the control expression can be an arithmetic expression • In most other languages, the control expression must be a Boolean expression Copyright © 2015 Pearson. All rights reserved. 1 -10
Clause Form • In many contemporary languages, then and else clauses can be single statements or compound statements • In Perl, all clauses must be delimited by braces (they must be compound) • In Python and Ruby, clauses are statement sequences without delimiters • Python uses indentation to define clauses if x > y : x = y print " x was greater than y" Copyright © 2015 Pearson. All rights reserved. 1 -11
Nesting Selectors • Java example if (sum == 0) if (count == 0) result = 0; else result = 1; • Which if does the else match? • Java's static semantics rule: else matches with the nearest previous if Copyright © 2015 Pearson. All rights reserved. 1 -12
Nesting Selectors (continued) • To force an alternative semantics, compound statements with delimiters may be used: if (sum == 0) { if (count == 0) result = 0; } else result = 1; • The above solution is used in C, C++, and C# Copyright © 2015 Pearson. All rights reserved. 1 -13
Nesting Selectors (continued) • Statement sequences as clauses: Ruby if sum == 0 then if count == 0 then result = 0 else result = 1 end Copyright © 2015 Pearson. All rights reserved. 1 -14
Nesting Selectors (continued) • Python if sum == 0 : if count == 0 : result = 0 else : result = 1 Copyright © 2015 Pearson. All rights reserved. 1 -15
Selection Statements u FORTRAN 90 and Ada solution l use special words to resolve semantics of nested selectors u e. g. (Ada) if. . then if … then … else … end if u Advantage: if. . then if … then … end if else … end if flexibility and readability Organization of Programming Languages-Cheng (Fall 2004) 16
Selector Expressions • In ML, F#, and Lisp, the selector is an expression; in F#: let y = if x > 0 then x else 2 * x - If the if expression returns a value, there must be an else clause (the expression could produce a unit type, which has no value). - The types of the values returned by then and else clauses must be the same. Copyright © 2015 Pearson. All rights reserved. 1 -17
Multiple-Way Selection Statements • Allow the selection of one of any number of statements or statement groups • Design Issues: 1. What is the form and type of the control expression? 2. How are the selectable segments specified? 3. Is execution flow through the structure restricted to include just a single selectable segment? 4. How are case values specified? 5. What is done about unrepresented expression values? Copyright © 2015 Pearson. All rights reserved. 1 -18
Multiple-Way Selection: Examples • C, C++, Java, and Java. Script switch (expression) { case const_expr 1: stmt 1; … case const_exprn: stmtn; [default: stmtn+1] } Copyright © 2015 Pearson. All rights reserved. 1 -19
Why do we need break statements? switch(month) { case 4: case 6: case 9: case 11; days = 30; break; case 2: //Find out if is leap year //divisible by 4 stuf days = 28 or 29; break; default: days = 31; } Copyright © 2015 Pearson. All rights reserved. 1 -20
Multiple-Way Selection: Examples • Design choices for C’s switch statement 1. Control expression can be only an integer type 2. Selectable segments can be statement sequences, blocks, or compound statements 3. Any number of segments can be executed in one execution of the construct (there is no implicit branch at the end of selectable segments) 4. default clause is for unrepresented values (if there is no default, the whole statement does nothing) Copyright © 2015 Pearson. All rights reserved. 1 -21
Selection Statements u Multiple Selection Constructs C: switch (expression) { case const_expr_1: statement_1; … case const_expr_k: statement_k; [default: def_statement; ] (optional) } Organization of Programming Languages-Cheng (Fall 2004) 22
Multiple-Way Selection: Examples • C# – Differs from C in that it has a static semantics rule that disallows the implicit execution of more than one segment – Each selectable segment must end with an unconditional branch (goto or break) – Also, in C# the control expression and the case constants can be strings Copyright © 2015 Pearson. All rights reserved. 1 -23
Multiple-Way Selection: Examples • Ruby has two forms of case statements • we’ll cover only one leap = case when year % 400 == 0 then true when year % 100 == 0 then false else year % 4 == 0 end Copyright © 2015 Pearson. All rights reserved. 1 -24
Implementing Multiple Selectors • Approaches: – Multiple conditional branches – Store case values in a table and use a linear search of the table – When there are more than ten cases, a hash table of case values can be used – If the number of cases is small and more than half of the whole range of case values are represented, an array whose indices are the case values and whose values are the case labels can be used Copyright © 2015 Pearson. All rights reserved. 1 -25
Multiple-Way Selection Using if • Multiple Selectors can appear as direct extensions to two-way selectors, using else -if clauses, for example in Python: if count < 10 : bag 1 = True elif count < 100 : bag 2 = True elif count < 1000 : bag 3 = True Copyright © 2015 Pearson. All rights reserved. 1 -26
Multiple-Way Selection Using if • The Python example can be written as a Ruby case when count < 10 then bag 1 = true when count < 100 then bag 2 = true when count < 1000 then bag 3 = true end Copyright © 2015 Pearson. All rights reserved. 1 -27
Scheme’s Multiple Selector • General form of a call to COND: (COND (predicate 1 expression 1) … (predicaten expressionn) [(ELSE expressionn+1)] ) - The ELSE clause is optional; ELSE is a synonym for true - Each predicate-expression pair is a parameter - Semantics: The value of the evaluation of COND is the value of the expression associated with the first predicate expression that is true Copyright © 2015 Pearson. All rights reserved. 1 -28
Iterative Statements • The repeated execution of a statement or compound statement – accomplished either by iteration or recursion; – Focus on iteration, since recursion is a unit-level control (e. g. , using functions) • General design issues for iteration control stmts: 1. How is iteration controlled? • Counter-controlled vs logical-controlled 2. Where is the control mechanism in the loop? • pretest (before loop body is executed) vs posttest (after loop body is executed) Copyright © 2015 Pearson. All rights reserved. 1 -29
Counter-Controlled Loops • A counting iterative statement has a loop variable, and a means of specifying the initial and terminal, and stepsize values • Design Issues: 1. What are the type and scope of the loop variable? 2. Should it be legal for the loop variable or loop parameters to be changed in the loop body, and if so, does the change affect loop control? 3. Should the loop parameters be evaluated only once, or once for every iteration? Copyright © 2015 Pearson. All rights reserved. 1 -30
Counter-Controlled Loops: Examples • C-based languages for ([expr_1] ; [expr_2] ; [expr_3]) statement - The expressions can be whole statements, or even statement sequences, with the statements separated by commas – The value of a multiple-statement expression is the value of the last statement in the expression – If the second expression is absent, it is an infinite loop • General Case –what interpretation when omit one? for ( init ; control ; increment) ; Copyright © 2015 Pearson. All rights reserved. 1 -31
Counter-Controlled Loops: • Design choices: - There is no explicit loop variable - Everything can be changed in the loop - The first expression is evaluated once, but the other two are evaluated with each iteration - It is legal to branch into the body of a for loop in C Copyright © 2015 Pearson. All rights reserved. 1 -32
Counter-Controlled Loops u C-based languages l Syntax: for ([expr_1] ; [expr_2] ; [expr_3]) loop body l Loop body can be single, compound, or null statement l Expressions can be whole statements, or even statement sequences, with the statements separated by commas l The value of a multiple-statement expression is the value of the last statement in the expression for (i = 0, j = 10; j == i; … l i++) All expressions of C’s for statement are optional u If expr_2 is absent, it is an infinite loop Organization of Programming Languages-Cheng (Fall 2004) 33
Counter-Controlled Loops for ([expr_1] ; [expr_2] ; [expr_3]) loop body u Operational Semantics: expr_1 loop: if expr_2 = 0 goto out [loop_body] expr_3 goto loop out: … % initialization (evaluate once) % loop control (each iter) % increment loop counter? Organization of Programming Languages-Cheng (Fall 2004) 34
Counter-Controlled Loops u Design choices for C: 1. There is no explicit loop variable or loop parameters u All involved variables can be changed in the loop body 2. It is legal to branch into loop body 3. The first expression is evaluated once, but the other two are evaluated with each iteration Organization of Programming Languages-Cheng (Fall 2004) 35
Counter-Controlled Loops: Examples • C++ differs from C in two ways: 1. The control expression can also be Boolean 2. The initial expression can include variable definitions (scope is from the definition to the end of the loop body) for (int i=0; i < len; i++) { … } • Java and C# – Differs from C++ in that the control(middle) expression must be Boolean Copyright © 2015 Pearson. All rights reserved. 1 -37
Counter-Controlled Loops u FORTRAN 95 l Syntax: Do label u u u var = initial, terminal [, stepsize] stepsize can be any value but zero parameters can be expressions Design choices: 1. Loop var must be integer; loop parameters can be expressions 2. The loop var cannot be changed in the loop, but loop parameters can because they are evaluated only once, it does not affect loop control 3. Single entry structure – loop can be entered through Do statement Organization of Programming Languages-Cheng (Fall 2004) 38
Counter-Controlled Loops u Fortran 95: Do label var = init_expression, terminal_expression [, step_expression] Operational Semantics for Fortran 95 Do statement 0) loop: init_value = init_expression terminal_value = terminal_expression step_value = step_expression do_var = init_value iteration_count = max(int((terminal_value– init_value+step_value)/step_value), if iteration_count 0 goto out [loop body] do_var = do_var + step_value iteration_count = interation_count – 1 goto loop Organization out: … of Programming Languages-Cheng (Fall 2004) 39
Counter-Controlled Loops u Another form of Do statement for FORTRAN 95 [name: ] DO variable = initial, terminal [, stepsize] … END DO [name] u Uses a special word for closing: END DO Organization of Programming Languages-Cheng (Fall 2004) 40
Counter-Controlled Loops u Ada l Syntax: for var in [reverse] discrete_range loop . . . end loop; l l reverse indicates that values of discrete range are assigned in reverse order Step size is always one (or next element in discrete_range) Organization of Programming Languages-Cheng (Fall 2004) 41
Counter-Controlled Loops: Examples • Python for loop_variable in object: - loop body [else: - else clause] – The object is often a range, which is either a list of values in brackets ([2, 4, 6]), or a call to the range function (range(5), which returns 0, 1, 2, 3, 4 – The loop variable takes on the values specified in the given range, one for each iteration – The else clause, which is optional, is executed if the loop terminates normally Copyright © 2015 Pearson. All rights reserved. 1 -42
Counter-Controlled Loops: Examples • F# – Because counters require variables, and functional languages do not have variables, counter-controlled loops must be simulated with recursive functions let rec for. Loop loop. Body reps = if reps <= 0 then () else loop. Body() for. Loop loop. Body, (reps – 1) - This defines the recursive function for. Loop with the parameters loop. Body (a function that defines the loop’s body) and the number of repetitions - () means do nothing and return nothing Copyright © 2015 Pearson. All rights reserved. 1 -43
Logically-Controlled Loops • Repetition control is based on a Boolean expression • More general than counter-controlled loops – Every counting loop can be built with a logical loop, but not vice-versa • Design issues: – Pretest or posttest? – Should the logically controlled loop be a special case of the counting loop statement or a separate statement? Copyright © 2015 Pearson. All rights reserved. 1 -44
Logically-Controlled Loops u Pascal has separate pretest and posttest logical loop statements (while-do and repeat-until) u C and C++ also have both while (count > 0) { … } do { … } while (count > 0); l Legal to branch into both while and do loop bodies with goto a label Organization of Programming Languages-Cheng (Fall 2004) 45
Logically-Controlled Loops u Ada has a pretest version, but no posttest u FORTRAN 77, 90, and 95 have neither u Perl has two pretest logical loops, while and until, but no posttest logical loop while (count > 0) { … } until (count == 0) { … } Organization of Programming Languages-Cheng (Fall 2004) 46
Logically-Controlled Loops: Examples • C and C++ have both pretest and posttest forms, in which the control expression can be arithmetic: while (control_expr) loop body do loop body while (control_expr) - In both C and C++ it is legal to branch into the body of a logically-controlled loop • Java is like C and C++, except the control expression must be Boolean (and the body can only be entered at the beginning) -- Java has no goto Copyright © 2015 Pearson. All rights reserved. 1 -47
Logically-Controlled Loops: Examples • F# – As with counter-controlled loops, logicallycontrolled loops can be simulated with recursive functions let rec while. Loop test body = if test() then body() while. Loop test body else () - This defines the recursive function while. Loop with parameters test and body, both functions. test defines the control expression Copyright © 2015 Pearson. All rights reserved. 1 -48
User-Located Loop Control Mechanisms • User modifies the control flow of program • More convenient for the programmers to decide a location for loop control (other than top or bottom of the loop) • Simple design for single loops (e. g. , break) • Design issues for nested loops 1. Should the conditional be part of the exit? 2. Should control be transferable out of more than one loop? Copyright © 2015 Pearson. All rights reserved. 1 -49
User-Located Loop Control Mechanisms • C , C++, Python, Ruby, and C# have unconditional unlabeled exits (break) • Java and Perl have unconditional labeled exits (break in Java, last in Perl) • C, C++, and Python have an unlabeled control statement, continue, that skips the remainder of the current iteration, but does not exit the loop • Java and Perl have labeled versions of continue Copyright © 2015 Pearson. All rights reserved. 1 -50
User-Located Loop Control u Exit statement: v Unconditional unlabeled exit: break (C, C++) for (index=0; index<10; index++) { … if (value < 0) break; } v Unconditional labeled exit: break (Java, C#), last (Perl) C#: outer. Loop: for (row=0; row<num. Rows; row++) for (col = 0; col < num. Cols; col++) { sum += matrix[row][col]; if (sum > 1000) break outer. Loop; } Perl: LINE: while (<STDIN>) { last LINE if /^$/; . . . } Organization of Programming Languages-Cheng (Fall 2004) 51
User-Located Loop Control u Skip the rest of loop body: v C/C++ have unlabeled control statement (continue) while (sum < 1000) { value = get. Next. Value(); if (value < 0) continue; sum += value; } v Java, Perl, and C# have statements similar to continue, except they can include labels that specify which loop is continued Organization of Programming Languages-Cheng (Fall 2004) 52
Iteration Based on Data Structures • The number of elements in a data structure controls loop iteration • Control mechanism is a call to an iterator function that returns the next element in some chosen order, if there is one; else loop is terminate • C's for can be used to build a user-defined iterator: for (p=root; p==NULL; traverse(p)){. . . } Copyright © 2015 Pearson. All rights reserved. 1 -53
Iteration Based on Data Structures u Loops are controlled by number of elements in a data structure l Perl, Javascript, PHP, and C# have such statements Perl: @values = (1, 2, 3, 4, 5); foreach $value (@values) { print “Value is $valuen”; } C#: String[] str. List = {“Bob”, “John”, “Carol” }; foreach (String name in str. List) … Organization of Programming Languages-Cheng (Fall 2004) 54
Iteration Based on Data Structures u More general approach l Utilizes a user-defined data structure and a userdefined function (called an iterator) to go through the structure’s elements l Java has a Collection interface that contains two methods: boolean add(Object obj) - adds elements to collection Iterator iterator() - used to visit the elements in the collection one by one. Organization of Programming Languages-Cheng (Fall 2004) 55
Iteration Based on Data Structures • (continued) PHP points at one element of the array - next moves current to the next element - reset moves current to the first element - current • Java 5. 0 (uses foreach) for, although it is called For arrays and any other class that implements the Iterable interface, e. g. , Array. List for (String my. Element : my. List) { … } Copyright © 2015 Pearson. All rights reserved. 1 -56
Iteration Based on Data Structures (continued) • C# and F# (and the other. NET languages) have generic library classes, like Java 5. 0 (for arrays, lists, stacks, and queues). Can iterate over these with the foreach statement. User-defined collections can implement the IEnumerator interface and also use foreach. List<String> names = new List<String>(); names. Add("Bob"); names. Add("Carol"); names. Add("Ted"); foreach (Strings name in names) Console. Write. Line ("Name: {0}", name); Copyright © 2015 Pearson. All rights reserved. 1 -57
Iteration Based on Data Structures (continued) • Ruby blocks are sequences of code, delimited by either braces or do and end – Blocks can be used with methods to create iterators – Predefined iterator methods (times, each, upto): 3. times {puts ″Hey!″} list. each {|value| puts value} (list is an array; value is a block parameter) 1. upto(5) {|x| print x, ″ ″} Iterators are implemented with blocks, which can also be defined by applications Copyright © 2015 Pearson. All rights reserved. 1 -58
Iteration Based on Data Structures (continued) • Ruby blocks are attached methods calls; they can have parameters (in vertical bars); they are executed when the method executes a yield statement def fibonacci(last) first, second = 1, 1 while first <= last yield first, second = second, first + second end puts "Fibonacci numbers less than 100 are: " fibonacci(100) {|num| print num, " "} puts - Ruby has a for statement, but Ruby converts them to upto method calls Copyright © 2015 Pearson. All rights reserved. 1 -59
Unconditional Branching • Transfers execution control to a specified place in the program • Represented one of the most heated debates in 1960’s and 1970’s • Major concern: Readability • Some languages do not support goto statement (e. g. , Java) • C# offers goto statement (can be used in switch statements) • Loop exit statements are restricted and somewhat camouflaged goto’s Copyright © 2015 Pearson. All rights reserved. 1 -60
Unconditional Branching u Transfers execution control to a specified location in the program goto label u u u Problem: readability l Some languages do not have them: e. g. , Java Loop exit statements are restricted and somewhat camouflaged goto’s Label forms: 1. Unsigned int constants: Pascal (with colon) FORTRAN (no colon) 2. Identifiers with colons: ALGOL 60, C 3. Variables as labels: PL/I Organization of Programming Languages-Cheng (Fall 2004) 61
Other Selection Statements Programming Language Principles Lecture 20 Prepared by Manuel E. Bermúdez, Ph. D. Associate Professor University of Florida
Structured Programming • Federal Law: Abandon Goto's ! • Originally, Fortran had goto's: if a. lt. b goto 10. . . 10 • Controversy surrounding Goto's: • Paper (letter to editor ACM Comm. ) in 1968 by E. Dijkstra: 1719 citations • "Goto statement Considered Harmful" • argument: Goto's create “spaghetti code". • https: //pdfs. semanticscholar. org/0446/c 87470 d 381 440 f 6 d 469 be 1 eda 31 b 09 b 40342. pdf
Structured Programming (cont’d) • Legacy: structured programming: use of • sequencing (; ) • alternation (if) • iteration (while) • Sufficient to solve any problem. • Part of focus on *control* during first 40 years in programming. • During 80's, 90's and beyond, focus shifted to *data* (OO-programming)
Structured Programming (cont’d) • Common (former) use of goto: break out of loop(s), maybe deeply nested: while true do begin if (. . . ) then goto 100; end; 100: . . .
Structured Programming (cont’d) • In C, this can be accomplished using a 'break' statement, but consider this. . . while (. . . ) { switch (. . . ) {. . . goto loop_done; { } loop_done: . . . /* break won't do */
Structured Programming (cont’d) • When executing a jump, we might be: • • exiting one or more procedure calls. exiting many nested loops. diving into the middle of a procedure diving into the middle of a loop. • What happens to the stack ? ? ?
Structured Programming (cont’d) • Goto's in general described using *continuations*: • A continuation captures the context (state) in which execution might continue. • Continuations essential to denotational semantics
Statement Sequencing • Basic assumption: • A sequence of statements will have side effects. • Not always desirable; easier to reason (prove correct) programs in which functions have no side effects. • Sometimes side-effects are *very* desirable. Example: rand() function. • want it to produce a different number each time it's called.
Statement Selection • Most languages use a variant of the original if. . . then. . . else introduced in Algol 60: if condition then statement else if condition then statement. . . else statement
Statement Selection (cont’d) switch (condition) { case a: block_a; case b: block_b : . . . default: block_c} is often syntactical sugar for if (condition == a) block_a else if (condition == b) block_b. . . else block_c
Short-Circuited Conditions • Design goal: implement if’s efficiently. • Jump code: efficient organization of code to take advantage of short-circuited boolean expressions. • Value of expression never stored in a register.
Short-Circuited Conditions (cont’d) • If the value of the entire expression is needed, we can still use jump code. • Example (Ada): found : = p /= null and then p. key =val; equivalent to if p /= null and then p. key=val then found : = true; else found : = false; end if;
Short-Circuited Conditions (cont’d) • Jump code: r 1 : = p if r 1=0 goto L 1 r 2 : = r 1 ->key if r 2 <> val goto L 1 r 1 : = 1 goto L 2 L 1: r 1: =0 L 2: found : = r 1
Case/Switch Statements • Alternative syntax for nested if. . . then. . . else statements. Example: i : = (* potentially complicated expression *) if i=1 then clause_A else if i=2 or i=7 then clause_B else if i >=3 and i <= 5 then clause_C else if i=10 then clause_D else clause_E
Corresponding CASE statement
Case/Switch Statements (cont’d) • Purpose of case statement is not only syntactic elegance, but efficiency. Wish to *compute* the address to which to branch. • So, list ten cases (range of values tested): • Store addresses starting at location T (jump table). • Calculate r 1 (the test expression value). • First test for r 1 out of range 1. . 10. • Subtract 1 from r 1, obtaining an offset (0. . 9). • Get address T[r 1], store in r 2. • Branch to (indirect) r 2.
Case/Switch Statements (cont’d) • Advantages: fast, occupies reasonable space if labels are dense. • Disadvantage: can occupy enormous amounts of space if values are not dense (e. g. 1, 3. . 5, 50000. . 50003)
Case/Switch Statements (cont’d) • Pascal, C don't allow ranges (avoid binary search). • Standard Pascal doesn't allow a default clause: • Run-time semantic error if no case matches expression. • Many Pascal compilers *do* allow it as an extension.
Case/Switch Statements (cont’d) • Modula provides an optional ELSE clause. • Ada requires labels to cover *ALL* values in the domain of the type of the expression. Ranges and an *others* clause are allowed. • C, Fortran 90: OK for expression to match no value: statement does nothing.
Case/Switch Statements (cont’d) • C is different in other respects: • A label can have an empty arm, • Control "falls" through to next label. • Effectively allows lists of values. • Example: switch (grade) { case 10: case 9: case 8: case 7: printf("Pass"); break; default: printf("Fail"); break; }
Case/Switch Statements (cont’d) • 'break' needed to prevent fallthrough. • If a value matches test expression, fall-through takes place • i. e. , there are no more comparisons.
Case/Switch Statements (cont’d) • Example: switch (grade) { case 10: case 9: case 8: case 7: num_pass++; case 6: borderline++; case 0: case 1: case: 2 case 3: case 4: case: 5 fail ++; default: total++; break; } • In C, a forgotten break can be a difficult bug to find.
Practical PL Level Iteration and Recursion Programming Language Principles Lecture 21 Prepared by Manuel E. Bermúdez, Ph. D. Associate Professor University of Florida
Iteration • Execute a block multiple times for its side effects. • Enumeration controlled loops: • Execute a block for every value in a finite set. • Fortran: do 10 i=1, 10, 2. . . 10 continue :
Classic Problems in Fortran • 'do' as prefix of assignment: do 7 i=j+3*4, 20 do loop do 7 i=j+3+4 assignment 'do 7 i' is a valid identifier. 'do' not a reserved word in Fortran. Need to look ahead arbitrary distance, to the 'comma'.
Classic Problems in Fortran (cont’d) • Loop body can change the loop index: do 10 i=2, 20 i=i-1 10 continue infinite loop • Goto's can jump into the middle of a loop. • So what's the value of the index, in that case ? ?
Classic Problems in Fortran (cont’d) • If goto branches out of loop, value of i is last assigned. If loop terminates normally, value of i is implementation-defined. • Last increment of i can cause overflow: negative value ? ? ? • Fortran loop is bottom-tested: loop body will execute at least once.
Pascal • (and Modula, and most languages with enumeration controlled loops): for i : = first to last by step do begin. . . end;
Pascal (cont’d) • Questions: 1. Can i, first or last be modified in the loop? • If so, what is the effect? 2. What if first > last? 3. What 's the value of i when done? 4. Can one jump from outside, into the loop? 5. What if first has a side effect on i, or on last, or vice-versa? • for i : = first to last by step do begin. . . end;
Pascal (cont’d) • Most languages prohibit modifying the loop index. • Very expensive to check at compile time. Need to check for: • Assignments to i • Nested loops that use i. • Passing i to a procedure by reference. • Reading i.
Pascal (cont’d) • What does this Pascal for statement do? i : = 7; for i : = i+1 to i+8 do begin. . . end;
Modern For Loops Are Top-Tested
Modern For Loops Are Top-Tested (cont’d) • Works only for positive steps. • In Pascal, for i : = 10 down to 1 do. . . • In Ada, for i in reverse 1. . 10 do. . . • In Modula, FOR i : = 10 to 1 STEP -1 compile-time constant
Modern For Loops Are Top-Tested (cont’d) • In C, C++, Java, it's simple. No loop index. for (e 1; e 2; e 3) body; Code is: e 1; L 2: if not e 2 goto L 1 body e 3; <--- any 'continue' branches here goto L 2 L 1: . . .
Modern For Loops Are Top-Tested (cont’d) • NOT equivalent to: e 1; while (e 2) { body; /* if this contains a 'continue', */ e 3; /* e 3 is not executed */ }
Modern For Loops Are Top-Tested (cont’d) • In C, programmer's responsibility: • effect of overflow. • index, other variables, can be modified inside loop. • e 1, e 2, e 3 are all optional. If e 2 is missing, it's considered to be a 1 (true).
Access to the Index Outside the Loop • Fortran IV, Pascal, leave the loop index undefined. • Fortran 77, Algol 60, leave the "last value assigned". • In Pascal, var c: 'a'. . 'z'; for c : = 'a' to 'z' do begin. . . end; (* what's the value of c ? *)
Access to the Index Outside the Loop (cont’d) • Compiler forced to generate slower code • Two branches in each iteration
Access to the Index Outside the Loop (cont’d) • Several languages (Algol W, Algol 68, Ada, Modula-3, new ISO C++): • loop header *declares* loop index. • loop index's type is inferred from loop bounds. • not visible outside the loop.
Combination Loops • Algol 60 allows a 'for-list' of enumerated values/ranges. • Syntax: Stmt Enumerator 'for' id ': =‘ Enumerator list ', ' 'do' Stmt Expr 'step' Expr 'until' Expr while Condition
Combination Loops (cont’d) • Algol Examples (all three are equivalent): for i : = 1, 3, 5, 9 do. . . for i : = 1 step 2 until 10 do. . . for i : = 1, i + 2 while i < 10 do. . .
Iterators • An iterator allows examination of the elements in a data structure, one at a time. • Various kinds of iterators available in Clu, Java • Java has a built-in iterator class.
Iterator Methods in Java Iterator ix = x. iterator(); • Constructs and initializes an iterator for the elements of x. • ix is the new iterator. • The class for x must define the iterator() method.
Iterator Methods in Java (cont’d) ix. has. Next() • Returns true iff x has a next element. ix. next() • Return next element; • Throws No. Such. Element. Exception if there is no next element.
Iterator Methods in Java (cont’d) ix. remove() • Removes last element returned by ix. next(). • Throws Unsupported. Method. EXception if method not implemented. • Throws Illegal. State. Exception if ix. next() not yet called or did not return an element.
Using the Iterator ix = x. iterator(); while (ix. has. Next()) examine(ix. next()); • Much better than for (int i=0; i<x. size(); i++) examine (x. get(i));
Advantages of Iterators • More abstraction. Object class "knows" how to iterate. • Often possible to implement next() more efficiently than get(). Example: linked list. • Data structures often have no get-by-index method.
"Faking" an Iterator in C • Using a "fake" iterator in C:
Logically Controlled Loops (cont’d) • Semantically less complex (fewer subtleties). • Execute statement (or block) until a condition becomes true/false (while) • Variations (syntactic sugar of each other): while condition do block; (Pascal, Modula) while (condition) block; (C, C++, Java) for i : = irrelevant_expression while condition do statement (Algol) 10 if negated-condition goto 20 block goto 10 20 (Fortran)
Logically Controlled Loops (cont’d) • Post-tested loops (execute at least once): repeat statements until condition (Pascal) do statement while condition (C, C++, Java)
Mid-Tested Loops (Quit Anytime): loop statement_list when condition exit. . . end (Modula-1) • 'exit' is built in, along with 'when', so exiting from a nested construct is impossible.
Modula-2 • Favored a simple EXIT Statement LOOP line = Read. Line; IF All. Blanks(line) THEN EXIT END; Consume. Line(line) END; • EXIT statements are only allowed to appear inside LOOPs. • Difficult to enforce.
Modula-3 • EXIT can abort a WHILE, REPEAT, or FOR loop. C: for (; ; ) { line = read_line(stdin); if (all_blanks(line)) break; consume_line (line); }
C Loops • [M. Scott says "for some reason, for(; ; ) has traditionally been favored over the equivalent while (1)". • The actual original reason was efficiency, not style: • older compilers would actually test the 1 each time around the while loop. • With today's compilers, it should make no difference.
Mid-Tested Loops (cont’d): • Euclid, Ada: loop. . . exit when condition; end loop;
Mid-Tested Loops (cont’d): • Java: • loops can be labeled, • 'break' statement has optional label. outer: while (true) { get_line(line); for (i=1; i<=length; i++) if line[i]='#' break outer; consume_line(line); }
Recursion • Any iterative formulation can be expressed as recursion, and vice versa. They are equally powerful. • Some functional languages do not allow iteration. • Iteration often more efficiently implemented.
Recursion (cont’d) • Optimizing compilers for functional languages usually generate very good code. • The use of iteration/recursion is mostly a matter of ease of use: • Iteration more efficient than recursion ? • Naive implementations are.
Recursion (cont’d) • For some problems, iteration seems natural. for (i=low; i<=high; i++) total += f(i); • For other problems, recursion seems more natural: let gcd a b = a eq b -> a | a < b -> gcd a (b-a) | gcd (a-b) b
Recursion (cont’d) • In C, int gcd (int a, int b) { if (a==b) return a; else if (a > b) return gcd(a-b, b); else return gcd(a, b-a); } • In both cases, the choice could go the other way.
Recursion (cont’d) • GCD in C, non-recursive: int gcd(int a, int b) { while(a!=b) if (a > b) a = a - b; else b = b - a; return a; }
Tail-Recursion • Additional computation never follows a recursive call. (nothing done as recursion unwinds). • No need to allocate stack space dynamically: we can reuse previous space. • Continuation-passing style: • can always avoid doing work after recursive call by passing that work into the recursive call, a continuation.
Tail-Recursion in Scheme
Normal-Order Evaluation • Normal order (passing unevaluated parameters) is used for macros in C. • Example: #define DIVIDES(n, a) (!((n) % (a))) /* true iff n % a is zero */ • Preprocessor replaces DIVIDES (x, y+z) (textually!, no evaluation) with (!((x) % (y+z)))
Normal-Order Evaluation (cont’d) • Parentheses (n), (a) are crucial. Without them, DIVIDES (x, y+z) is replaced with (!(x % y+z)) which is equivalent to (!((x % y)+z))
Normal-Order Evaluation (cont’d) • Macros are problematic: #define MAX(a, b) ((a) > (b) ? (a) : (b) MAX(x++, y++) will increment either x (or y) TWICE ! ((x++) > (y++) ? (x++) : (y++)
Normal-Order Evaluation (cont’d) • Advantage of macros: • Efficient ! No function call overhead. • In C++, 'inline' tells compiler to try to convert function call to a macro. • Algol 60 uses normal order, with PL order also available.
Guarded Commands • Designed by Dijkstra • Purpose: to support a new programming methodology that supported verification (correctness) during development • Basis for two linguistic mechanisms for concurrent programming (in CSP) • Basic Idea: if the order of evaluation is not important, the program should not specify one Copyright © 2015 Pearson. All rights reserved. 1 -134
Selection Guarded Command • Form if <Boolean expr> -> <statement> [] <Boolean expr> -> <statement>. . . [] <Boolean expr> -> <statement> fi • Semantics: when construct is reached, – Evaluate all Boolean expressions – If more than one are true, choose one nondeterministically – If none are true, it is a runtime error Copyright © 2015 Pearson. All rights reserved. 1 -135
Loop Guarded Command • Form <Boolean> -> <statement> [] <Boolean> -> <statement>. . . [] <Boolean> -> <statement> do od • Semantics: for each iteration – Evaluate all Boolean expressions – If more than one are true, choose one nondeterministically; then start loop again – If none are true, exit loop Copyright © 2015 Pearson. All rights reserved. 1 -136
Guarded Commands: Rationale • Connection between control statements and program verification is intimate • Verification is impossible with goto statements • Verification is possible with only selection and logical pretest loops • Verification is relatively simple with only guarded commands Copyright © 2015 Pearson. All rights reserved. 1 -137
Non-Determinacy • Construct in which the choice between alternatives is deliberately unspecified. • Example: n + n++ in C (order of evaluation unspecified)
Non-Determinacy (cont’d) • Sometimes makes it easier to reason about program. • Mostly a set of guarded commands from which any guard that is true can be selected.
Non-Determinacy (cont’d) • Example (SR, adopted Dykstra's guarded command): if a >= b -> max : = a; [] b >= a -> max : = b; fi • Nondeterministic choice made among guards that evaluate to true.
Non-Determinacy (cont’d) • Also used for loops: do a > b -> a : = a - b; [] b > a -> b : = b - a; od gcd : = a • Loop quits when no guard is true. • We wish to ensure fairness: each candidate equally likely to execute.
Conclusions • Variety of statement-level structures • Choice of control statements beyond selection and logical pretest loops is a trade-off between language size and writability • Functional and logic programming languages use quite different control structures Copyright © 2015 Pearson. All rights reserved. 1 -142
- Slides: 141