control flow
play

CONTROL FLOW PRINCIPLES OF PROGRAMMING LANGUAGES Norbert Zeh - PowerPoint PPT Presentation

CONTROL FLOW PRINCIPLES OF PROGRAMMING LANGUAGES Norbert Zeh Winter 2018 Dalhousie University 1/40 LANGUAGE MECHANISMS FOR CONTROL FLOW The successful programmer thinks in terms of basic principles of control flow, not in terms of syntax!


  1. JAVA EXAMPLES b += "world"; b = This is b's value a = This is b's value Output: System.out.println("b = " + b); System.out.println("a = " + a); b.append("This is b's value."); StringBuffer b = a; StringBuffer a = new StringBuffer(); b = hi world a = hi Output: System.out.println("b = " + b); System.out.println("a = " + a); String b = a; int a = 5; String a = "hi "; true Output: System.out.println(a == b); b.change(); Obj b = a; Obj a = new Obj(); b = 15 a = 5 Output: System.out.println("b = " + b); System.out.println("a = " + a); b += 10; int b = a; 9/40

  2. JAVA EXAMPLES b += "world"; b = This is b's value a = This is b's value Output: System.out.println("b = " + b); System.out.println("a = " + a); b.append("This is b's value."); StringBuffer b = a; StringBuffer a = new StringBuffer(); b = hi world a = hi Output: System.out.println("b = " + b); System.out.println("a = " + a); String b = a; int a = 5; String a = "hi "; true Output: System.out.println(a == b); b.change(); Obj b = a; Obj a = new Obj(); b = 15 a = 5 Output: System.out.println("b = " + b); System.out.println("a = " + a); b += 10; int b = a; 9/40

  3. JAVA EXAMPLES b += "world"; b = This is b's value a = This is b's value Output: System.out.println("b = " + b); System.out.println("a = " + a); b.append("This is b's value."); StringBuffer b = a; StringBuffer a = new StringBuffer(); b = hi world a = hi Output: System.out.println("b = " + b); System.out.println("a = " + a); String b = a; int a = 5; String a = "hi "; true Output: System.out.println(a == b); b.change(); Obj b = a; Obj a = new Obj(); b = 15 a = 5 Output: System.out.println("b = " + b); System.out.println("a = " + a); b += 10; int b = a; 9/40

  4. JAVA EXAMPLES b += "world"; b = This is b's value a = This is b's value Output: System.out.println("b = " + b); System.out.println("a = " + a); b.append("This is b's value."); StringBuffer b = a; StringBuffer a = new StringBuffer(); b = hi world a = hi Output: System.out.println("b = " + b); System.out.println("a = " + a); String b = a; int a = 5; String a = "hi "; true Output: System.out.println(a == b); b.change(); Obj b = a; Obj a = new Obj(); b = 15 a = 5 Output: System.out.println("b = " + b); System.out.println("a = " + a); b += 10; int b = a; 9/40

  5. JAVA EXAMPLES b += "world"; b = This is b's value a = This is b's value Output: System.out.println("b = " + b); System.out.println("a = " + a); b.append("This is b's value."); StringBuffer b = a; StringBuffer a = new StringBuffer(); b = hi world a = hi Output: System.out.println("b = " + b); System.out.println("a = " + a); String b = a; int a = 5; String a = "hi "; true Output: System.out.println(a == b); b.change(); Obj b = a; Obj a = new Obj(); b = 15 a = 5 Output: System.out.println("b = " + b); System.out.println("a = " + a); b += 10; int b = a; 9/40

  6. JAVA EXAMPLES b += "world"; b = This is b's value a = This is b's value Output: System.out.println("b = " + b); System.out.println("a = " + a); b.append("This is b's value."); StringBuffer b = a; StringBuffer a = new StringBuffer(); b = hi world a = hi Output: System.out.println("b = " + b); System.out.println("a = " + a); String b = a; int a = 5; String a = "hi "; true Output: System.out.println(a == b); b.change(); Obj b = a; Obj a = new Obj(); b = 15 a = 5 Output: System.out.println("b = " + b); System.out.println("a = " + a); b += 10; int b = a; 9/40

  7. EVALUATION ORDER WITHIN EXPRESSIONS It is usually unwise to write expressions where a side effect of evaluating an operand is to change another operand used in the same expression. Some languages explicitly forbid side effects in expression operands. Possible problems: • Evaluation order is often left to the compiler (i.e., undefined in the language specification). Thus, such side effects may lead to unexpected results. • Evaluation order impacts register allocation, instruction scheduling, etc. By fixing a particular evaluation ordering, some code improvements may not be possible. This impacts performance. 10/40

  8. EVALUATION ORDER WITHIN EXPRESSIONS It is usually unwise to write expressions where a side effect of evaluating an operand is to change another operand used in the same expression. Some languages explicitly forbid side effects in expression operands. Possible problems: • Evaluation order is often left to the compiler (i.e., undefined in the language specification). Thus, such side effects may lead to unexpected results. • Evaluation order impacts register allocation, instruction scheduling, etc. By fixing a particular evaluation ordering, some code improvements may not be possible. This impacts performance. 10/40

  9. EVALUATION ORDER WITHIN EXPRESSIONS It is usually unwise to write expressions where a side effect of evaluating an operand is to change another operand used in the same expression. Some languages explicitly forbid side effects in expression operands. Possible problems: • Evaluation order is often left to the compiler (i.e., undefined in the language specification). Thus, such side effects may lead to unexpected results. • Evaluation order impacts register allocation, instruction scheduling, etc. By fixing a particular evaluation ordering, some code improvements may not be possible. This impacts performance. 10/40

  10. EVALUATION ORDER WITHIN EXPRESSIONS It is usually unwise to write expressions where a side effect of evaluating an operand is to change another operand used in the same expression. Some languages explicitly forbid side effects in expression operands. Possible problems: • Evaluation order is often left to the compiler (i.e., undefined in the language specification). Thus, such side effects may lead to unexpected results. • Evaluation order impacts register allocation, instruction scheduling, etc. By fixing a particular evaluation ordering, some code improvements may not be possible. This impacts performance. 10/40

  11. F N ( N th Fibonacci number) AN EXAMPLE WITH SIDE EFFECTS IN C N m M 2 1 1 3 1 2 2 4 4 5 4 8 6 8 16 M 2 N 2 Actual M for(i = m = M = 1; N - ++i; M = m + (m = M)); 1 What does this code compute? The answer depends on the evaluation order of the two subexpressions of M = m + (m = M) . Probably intented N m M 2 1 3 8 1 2 4 2 3 5 3 5 6 5 11/40

  12. F N ( N th Fibonacci number) AN EXAMPLE WITH SIDE EFFECTS IN C N m M 2 1 1 3 1 2 2 4 4 5 4 8 6 8 16 M 2 N 2 Actual M for(i = m = M = 1; N - ++i; M = m + (m = M)); 1 What does this code compute? The answer depends on the evaluation order of the two subexpressions of M = m + (m = M) . Probably intented N m M 2 1 3 8 1 2 4 2 3 5 3 5 6 5 11/40

  13. AN EXAMPLE WITH SIDE EFFECTS IN C 4 m M 2 1 1 3 1 2 2 Actual 4 5 4 8 6 8 16 M 2 N 2 N 8 for(i = m = M = 1; N - ++i; M = m + (m = M)); 1 What does this code compute? The answer depends on the evaluation order of the two subexpressions of M = m + (m = M) . Probably intented N m M 2 1 3 1 2 4 2 3 5 3 5 6 5 11/40 M = F N ( N th Fibonacci number)

  14. AN EXAMPLE WITH SIDE EFFECTS IN C 2 N m M 2 1 1 3 1 4 for(i = m = M = 1; N - ++i; M = m + (m = M)); 2 4 5 4 8 6 8 16 Actual 8 5 6 What does this code compute? The answer depends on the evaluation order of the two subexpressions of M = m + (m = M) . Probably intented N m M 2 1 1 3 1 2 4 2 3 5 3 5 11/40 M = 2 N − 2 M = F N ( N th Fibonacci number)

  15. SHORT-CIRCUIT EVALUATION OF BOOLEAN EXPRESSIONS (and a b) : If a is false, b has no effect on the value of the whole expression. (or a b) : If a is true, b has no effect on the value of the whole expression. Short-circuit evaluation If the value of the expression does not depend on b , the evaluation of b is skipped. This is useful, both in terms of optimization and semantically. Some languages provide both regular and short-circuit versions of Boolean operators. Ada: • and vs and then • or vs or else 12/40

  16. SHORT-CIRCUIT EVALUATION OF BOOLEAN EXPRESSIONS (and a b) : If a is false, b has no effect on the value of the whole expression. (or a b) : If a is true, b has no effect on the value of the whole expression. Short-circuit evaluation If the value of the expression does not depend on b , the evaluation of b is skipped. This is useful, both in terms of optimization and semantically. Some languages provide both regular and short-circuit versions of Boolean operators. Ada: • and vs and then • or vs or else 12/40

  17. SHORT-CIRCUIT EVALUATION OF BOOLEAN EXPRESSIONS (and a b) : If a is false, b has no effect on the value of the whole expression. (or a b) : If a is true, b has no effect on the value of the whole expression. Short-circuit evaluation If the value of the expression does not depend on b , the evaluation of b is skipped. This is useful, both in terms of optimization and semantically. Some languages provide both regular and short-circuit versions of Boolean operators. Ada: • and vs and then • or vs or else 12/40

  18. SHORT-CIRCUIT EVALUATION OF BOOLEAN EXPRESSIONS (and a b) : If a is false, b has no effect on the value of the whole expression. (or a b) : If a is true, b has no effect on the value of the whole expression. Short-circuit evaluation If the value of the expression does not depend on b , the evaluation of b is skipped. This is useful, both in terms of optimization and semantically. Some languages provide both regular and short-circuit versions of Boolean operators. Ada: • and vs and then • or vs or else 12/40

  19. COMMON IDIOMS ENABLED BY SHORT-CIRCUIT EVALUATION Checking for NULL pointers in C: while (p != NULL && p->e != val) { p = p->next; } Exit on failure in Perl: open(F, "file") or die; Short-circuit and as if-statement in Perl or shell scripts: if (x > max) then max = x; becomes (x > max) && max = x; 13/40

  20. COMMON IDIOMS ENABLED BY SHORT-CIRCUIT EVALUATION Checking for NULL pointers in C: while (p != NULL && p->e != val) { p = p->next; } Exit on failure in Perl: open(F, "file") or die; Short-circuit and as if-statement in Perl or shell scripts: if (x > max) then max = x; becomes (x > max) && max = x; 13/40

  21. COMMON IDIOMS ENABLED BY SHORT-CIRCUIT EVALUATION Checking for NULL pointers in C: while (p != NULL && p->e != val) { p = p->next; } Exit on failure in Perl: open(F, "file") or die; Short-circuit and as if-statement in Perl or shell scripts: if (x > max) then max = x; becomes (x > max) && max = x; 13/40

  22. SEQUENCING LISP: (progn (setq a 4) (setq b 5)) 5 LISP: (prog2 (setq a 4) (setq b 5) (setq c 6) • The value of the second subexpression 4 LISP: (prog1 (setq a 4) (setq b 5)) • The value of the first subexpression 5 5 In imperative programming languages, sequencing comes naturally, without a a = 4, b = 5; C: • The value of the last subexpression (most common) Issue: What’s the value of a sequence of expressions/statements? constructs for sequencing. Mixed imperative/function languages (LISP, Scheme, …) often provide special need for special syntax to support it. 14/40

  23. SEQUENCING LISP: (progn (setq a 4) (setq b 5)) 5 LISP: (prog2 (setq a 4) (setq b 5) (setq c 6) • The value of the second subexpression 4 LISP: (prog1 (setq a 4) (setq b 5)) • The value of the first subexpression 5 5 In imperative programming languages, sequencing comes naturally, without a a = 4, b = 5; C: • The value of the last subexpression (most common) Issue: What’s the value of a sequence of expressions/statements? constructs for sequencing. Mixed imperative/function languages (LISP, Scheme, …) often provide special need for special syntax to support it. 14/40

  24. SEQUENCING LISP: (progn (setq a 4) (setq b 5)) 5 LISP: (prog2 (setq a 4) (setq b 5) (setq c 6) • The value of the second subexpression 4 LISP: (prog1 (setq a 4) (setq b 5)) • The value of the first subexpression 5 14/40 In imperative programming languages, sequencing comes naturally, without a a = 4, b = 5; C: • The value of the last subexpression (most common) Issue: What’s the value of a sequence of expressions/statements? constructs for sequencing. Mixed imperative/function languages (LISP, Scheme, …) often provide special need for special syntax to support it. ⇒ 5 =

  25. SEQUENCING In imperative programming languages, sequencing comes naturally, without a 5 LISP: (prog2 (setq a 4) (setq b 5) (setq c 6) • The value of the second subexpression 4 LISP: (prog1 (setq a 4) (setq b 5)) • The value of the first subexpression LISP: (progn (setq a 4) (setq b 5)) 14/40 a = 4, b = 5; C: • The value of the last subexpression (most common) Issue: What’s the value of a sequence of expressions/statements? constructs for sequencing. Mixed imperative/function languages (LISP, Scheme, …) often provide special need for special syntax to support it. ⇒ 5 = ⇒ 5 =

  26. SEQUENCING In imperative programming languages, sequencing comes naturally, without a 5 LISP: (prog2 (setq a 4) (setq b 5) (setq c 6) • The value of the second subexpression LISP: (prog1 (setq a 4) (setq b 5)) • The value of the first subexpression LISP: (progn (setq a 4) (setq b 5)) a = 4, b = 5; C: • The value of the last subexpression (most common) Issue: What’s the value of a sequence of expressions/statements? constructs for sequencing. Mixed imperative/function languages (LISP, Scheme, …) often provide special need for special syntax to support it. 14/40 ⇒ 5 = ⇒ 5 = ⇒ 4 =

  27. SEQUENCING a = 4, b = 5; LISP: (prog2 (setq a 4) (setq b 5) (setq c 6) • The value of the second subexpression LISP: (prog1 (setq a 4) (setq b 5)) • The value of the first subexpression In imperative programming languages, sequencing comes naturally, without a LISP: (progn (setq a 4) (setq b 5)) C: • The value of the last subexpression (most common) Issue: What’s the value of a sequence of expressions/statements? constructs for sequencing. Mixed imperative/function languages (LISP, Scheme, …) often provide special need for special syntax to support it. 14/40 ⇒ 5 = ⇒ 5 = ⇒ 4 = ⇒ 5 =

  28. GOTO AND ALTERNATIVES Use of goto is bad programming practice if the same effect can be achieved using different constructs. Sometimes, it is unavoidable: • Break out of a loop • Break out of a subroutine • Break out of a deeply nested context Many languages provide alternatives: • One-and-a-half loop • return statement • Structured exception handling 15/40

  29. GOTO AND ALTERNATIVES Use of goto is bad programming practice if the same effect can be achieved using different constructs. Sometimes, it is unavoidable: • Break out of a loop • Break out of a subroutine • Break out of a deeply nested context Many languages provide alternatives: • One-and-a-half loop • return statement • Structured exception handling 15/40

  30. GOTO AND ALTERNATIVES Use of goto is bad programming practice if the same effect can be achieved using different constructs. Sometimes, it is unavoidable: • Break out of a loop • Break out of a subroutine • Break out of a deeply nested context Many languages provide alternatives: • One-and-a-half loop • return statement • Structured exception handling 15/40

  31. SELECTION (ALTERNATION) else default action default action default: ... case pattern2: option2 case pattern1: option1 switch value of Switch statement: ... Standard if-then-else statement: elsif cond3 then option3 elsif cond2 then option2 cond1 then option1 if Multi-way if-then-else statement: else that if cond then this 16/40

  32. SELECTION (ALTERNATION) else default action default action default: ... case pattern2: option2 case pattern1: option1 switch value of Switch statement: ... Standard if-then-else statement: elsif cond3 then option3 elsif cond2 then option2 cond1 then option1 if Multi-way if-then-else statement: else that if cond then this 16/40

  33. SELECTION (ALTERNATION) else default action default action default: ... case pattern2: option2 case pattern1: option1 switch value of Switch statement: ... Standard if-then-else statement: elsif cond3 then option3 elsif cond2 then option2 cond1 then option1 if Multi-way if-then-else statement: else that if cond then this 16/40

  34. Principal motivation: Generate more efficient code! SWITCH STATEMENTS Switch statements are a special case of if/then/elsif/else statements. Compiler can use different methods to generate efficient code: • Sequential testing • Binary search • Hash table • Jump table 17/40

  35. SWITCH STATEMENTS Switch statements are a special case of if/then/elsif/else statements. Principal motivation: Generate more efficient code! Compiler can use different methods to generate efficient code: • Sequential testing • Binary search • Hash table • Jump table 17/40

  36. SWITCH STATEMENTS Switch statements are a special case of if/then/elsif/else statements. Principal motivation: Generate more efficient code! Compiler can use different methods to generate efficient code: • Sequential testing • Binary search • Hash table • Jump table 17/40

  37. SWITCH STATEMENTS Switch statements are a special case of if/then/elsif/else statements. Principal motivation: Generate more efficient code! Compiler can use different methods to generate efficient code: • Sequential testing • Binary search • Hash table • Jump table 17/40

  38. IMPLEMENTATION OF IF STATEMENTS L1: if R1 == 2 goto L2 L6: ... L5: call default_action goto L6 call option4 L4: if R1 != 10 goto L5 goto L6 call option3 if R1 > 5 goto L4 L3: if R1 < 3 goto L4 goto L6 L2: call option2 if R1 != 7 goto L3 goto L6 if i == 1: call option1 if R1 != 1 goto L1 Assume i is stored in register R1 . default_action() else: option4() elsif i == 10: option3() elsif i in [3, 4, 5]: option2() elsif i in [2, 7]: option1() 18/40

  39. IMPLEMENTATION OF IF STATEMENTS L1: if R1 == 2 goto L2 L6: ... L5: call default_action goto L6 call option4 L4: if R1 != 10 goto L5 goto L6 call option3 if R1 > 5 goto L4 L3: if R1 < 3 goto L4 goto L6 L2: call option2 if R1 != 7 goto L3 goto L6 if i == 1: call option1 if R1 != 1 goto L1 Assume i is stored in register R1 . default_action() else: option4() elsif i == 10: option3() elsif i in [3, 4, 5]: option2() elsif i in [2, 7]: option1() 18/40

  40. IMPLEMENTATION OF SWITCH STATEMENTS: JUMP TABLE L5: call default_action &L5 goto L7 &L2 L4: call option4 &L5 goto L7 &L5 &L4 &L3 goto L7 L6: if R1 < 1 goto L5 if R1 > 10 goto L5 R1 := R1 - 1 R2 := T[R1] goto *R2 L7: ... L3: call option3 goto L7 case i: option4() 1: option1() 2, 7: option2() 3, 4, 5: option3() 10: otherwise: default_action() &L3 Assume i is stored in register R1 . T: &L1 L1: call option1 &L2 goto L7 &L3 L2: call option2 19/40

  41. IMPLEMENTATION OF SWITCH STATEMENTS: JUMP TABLE L5: call default_action &L5 goto L7 &L2 L4: call option4 &L5 goto L7 &L5 &L4 &L3 goto L7 L6: if R1 < 1 goto L5 if R1 > 10 goto L5 R1 := R1 - 1 R2 := T[R1] goto *R2 L7: ... L3: call option3 goto L7 case i: option4() 1: option1() 2, 7: option2() 3, 4, 5: option3() 10: otherwise: default_action() &L3 Assume i is stored in register R1 . T: &L1 L1: call option1 &L2 goto L7 &L3 L2: call option2 19/40

  42. IMPLEMENTATION OF SWITCH STATEMENTS a large table Compilers often use different strategies based on the specific code. No single implementation is best in all circumstances. No storage overhead Fast, but slower than table lookup Binary search: No storage overhead Potentially slow Linear search: stored individually; again, possibly Jump table: Elements in a range need to be More complicated the right branch Fast: one hash table access to find Hash table: per possible value Potentially large table: one entry right branch Fast: one table lookup to find the 20/40

  43. IMPLEMENTATION OF SWITCH STATEMENTS a large table Compilers often use different strategies based on the specific code. No single implementation is best in all circumstances. No storage overhead Fast, but slower than table lookup Binary search: No storage overhead Potentially slow Linear search: stored individually; again, possibly Jump table: Elements in a range need to be More complicated the right branch Fast: one hash table access to find Hash table: per possible value right branch 20/40 + Fast: one table lookup to find the − Potentially large table: one entry

  44. IMPLEMENTATION OF SWITCH STATEMENTS a large table Compilers often use different strategies based on the specific code. No single implementation is best in all circumstances. No storage overhead Fast, but slower than table lookup Binary search: No storage overhead Potentially slow Linear search: stored individually; again, possibly Jump table: the right branch Hash table: per possible value right branch 20/40 + Fast: one table lookup to find the + Fast: one hash table access to find − Potentially large table: one entry − More complicated − Elements in a range need to be

  45. IMPLEMENTATION OF SWITCH STATEMENTS Jump table: Compilers often use different strategies based on the specific code. No single implementation is best in all circumstances. No storage overhead Fast, but slower than table lookup Binary search: Linear search: a large table stored individually; again, possibly Hash table: the right branch per possible value right branch 20/40 + Fast: one table lookup to find the + Fast: one hash table access to find − Potentially large table: one entry − More complicated − Elements in a range need to be − Potentially slow + No storage overhead

  46. IMPLEMENTATION OF SWITCH STATEMENTS Jump table: Compilers often use different strategies based on the specific code. No single implementation is best in all circumstances. Binary search: Linear search: a large table stored individually; again, possibly the right branch Hash table: per possible value right branch 20/40 + Fast: one table lookup to find the + Fast: one hash table access to find − Potentially large table: one entry − More complicated − Elements in a range need to be ± Fast, but slower than table lookup − Potentially slow + No storage overhead + No storage overhead

  47. IMPLEMENTATION OF SWITCH STATEMENTS Jump table: Compilers often use different strategies based on the specific code. No single implementation is best in all circumstances. Binary search: Linear search: a large table stored individually; again, possibly the right branch Hash table: per possible value right branch 20/40 + Fast: one table lookup to find the + Fast: one hash table access to find − Potentially large table: one entry − More complicated − Elements in a range need to be ± Fast, but slower than table lookup − Potentially slow + No storage overhead + No storage overhead

  48. ITERATION Enumeration-controlled loops: • Example: for-loop • One iteration per element in finite set • The number of iterations is known in advance. Logically controlled loops: • Example: while-loop • Executed until a Boolean condition changes • The number of iterations is not known in advance. Some languages do not have loop constructs (Scheme, Haskell, …). They use tail recursion instead. 21/40

  49. ITERATION Enumeration-controlled loops: • Example: for-loop • One iteration per element in finite set • The number of iterations is known in advance. Logically controlled loops: • Example: while-loop • Executed until a Boolean condition changes • The number of iterations is not known in advance. Some languages do not have loop constructs (Scheme, Haskell, …). They use tail recursion instead. 21/40

  50. LOGICALLY CONTROLLED LOOPS loop { } ... if (cond2) exit; ... if (cond1) exit; ... Mid-loop test or “one-and-a-half loop”: Pre-loop test: } while (cond); ... do { Post-loop test: } ... while (cond) { 22/40

  51. LOGICALLY CONTROLLED LOOPS loop { } ... if (cond2) exit; ... if (cond1) exit; ... Mid-loop test or “one-and-a-half loop”: Pre-loop test: } while (cond); ... do { Post-loop test: } ... while (cond) { 22/40

  52. LOGICALLY CONTROLLED LOOPS loop { } ... if (cond2) exit; ... if (cond1) exit; ... Mid-loop test or “one-and-a-half loop”: Pre-loop test: } while (cond); ... do { Post-loop test: } ... while (cond) { 22/40

  53. TRADE-OFFS IN ITERATION CONSTRUCTS (1) goto L1 L2: ... goto L1 step statements if not R1 goto L2 L1: R1 := evaluate cond init } statements; for (init; cond; step) { L2: ... statements Logically controlled loops: if not R1 goto L2 L1: R1 := evaluate cond } statements; while (cond) { using logically controlled loops! idiom in implementing enumeration syntactic sugar for the init-test-step The for-loop in C/C++ is merely Expensive Flexible 23/40

  54. TRADE-OFFS IN ITERATION CONSTRUCTS (1) goto L1 L2: ... goto L1 step statements if not R1 goto L2 L1: R1 := evaluate cond init } statements; for (init; cond; step) { L2: ... statements Logically controlled loops: if not R1 goto L2 L1: R1 := evaluate cond } statements; while (cond) { using logically controlled loops! idiom in implementing enumeration syntactic sugar for the init-test-step The for-loop in C/C++ is merely Expensive 23/40 + Flexible

  55. TRADE-OFFS IN ITERATION CONSTRUCTS (1) goto L1 L2: ... goto L1 step statements if not R1 goto L2 L1: R1 := evaluate cond init } statements; for (init; cond; step) { L2: ... statements Logically controlled loops: if not R1 goto L2 L1: R1 := evaluate cond } statements; while (cond) { using logically controlled loops! idiom in implementing enumeration syntactic sugar for the init-test-step The for-loop in C/C++ is merely 23/40 + Flexible − Expensive

  56. TRADE-OFFS IN ITERATION CONSTRUCTS (1) goto L1 L2: ... goto L1 step statements if not R1 goto L2 L1: R1 := evaluate cond init } statements; for (init; cond; step) { L2: ... statements Logically controlled loops: if not R1 goto L2 L1: R1 := evaluate cond } statements; while (cond) { using logically controlled loops! idiom in implementing enumeration syntactic sugar for the init-test-step The for-loop in C/C++ is merely 23/40 + Flexible − Expensive

  57. TRADE-OFFS IN ITERATION CONSTRUCTS (1) goto L1 L2: ... goto L1 step statements if not R1 goto L2 L1: R1 := evaluate cond init } statements; for (init; cond; step) { L2: ... statements Logically controlled loops: if not R1 goto L2 L1: R1 := evaluate cond } statements; while (cond) { using logically controlled loops! idiom in implementing enumeration syntactic sugar for the init-test-step The for-loop in C/C++ is merely 23/40 + Flexible − Expensive

  58. TRADE-OFFS IN ITERATION CONSTRUCTS (2) goto L1 L2: ... goto L1 decrement R1 statements L1: if not R1 goto L2 step) + 1 R1 := floor((end - start) / the loop is not allowed: If modifying the loop variable inside L2: ... R1 + R3 Potentially much more efficient: R1 = statements L1: if R1 > R2 goto L2 R3 := step R2 := end R1 := start the loop is allowed: If modifying the loop variable inside END statements FOR i = start TO end BY step DO 24/40

  59. TRADE-OFFS IN ITERATION CONSTRUCTS (2) goto L1 L2: ... goto L1 decrement R1 statements L1: if not R1 goto L2 step) + 1 R1 := floor((end - start) / the loop is not allowed: If modifying the loop variable inside L2: ... R1 + R3 Potentially much more efficient: R1 = statements L1: if R1 > R2 goto L2 R3 := step R2 := end R1 := start the loop is allowed: If modifying the loop variable inside END statements FOR i = start TO end BY step DO 24/40

  60. TRADE-OFFS IN ITERATION CONSTRUCTS (2) goto L1 L2: ... goto L1 decrement R1 statements L1: if not R1 goto L2 step) + 1 R1 := floor((end - start) / the loop is not allowed: If modifying the loop variable inside L2: ... R1 + R3 Potentially much more efficient: R1 = statements L1: if R1 > R2 goto L2 R3 := step R2 := end R1 := start the loop is allowed: If modifying the loop variable inside END statements FOR i = start TO end BY step DO 24/40

  61. LABELLED BREAK AND CONTINUE “Break” statement (“last“ in Perl): Exit the nearest enclosing for-, do-, while- or switch-statement. “Continue” statement (“next” in Perl): Skip the rest of the current iteration. Both statements may be followed by a label that specifies • An enclosing loop (continue) or • Any enclosing statement (break). A loop may have a finally part, which is always executed no matter whether the iteration executes normally or is terminated using a continue or break statement. 25/40

  62. LABELLED BREAK AND CONTINUE “Break” statement (“last“ in Perl): Exit the nearest enclosing for-, do-, while- or switch-statement. “Continue” statement (“next” in Perl): Skip the rest of the current iteration. Both statements may be followed by a label that specifies • An enclosing loop (continue) or • Any enclosing statement (break). A loop may have a finally part, which is always executed no matter whether the iteration executes normally or is terminated using a continue or break statement. 25/40

  63. LABELLED BREAK AND CONTINUE “Break” statement (“last“ in Perl): Exit the nearest enclosing for-, do-, while- or switch-statement. “Continue” statement (“next” in Perl): Skip the rest of the current iteration. Both statements may be followed by a label that specifies • An enclosing loop (continue) or • Any enclosing statement (break). A loop may have a finally part, which is always executed no matter whether the iteration executes normally or is terminated using a continue or break statement. 25/40

  64. ITERATORS AND GENERATORS Often, for-loops are used to iterate over sequences of elements (stored in a data structure, generated by a procedure, …). Iterators/generators provide a clean idiom for iterating over a sequence without a need to know how the sequence is generated. Generators in Python: def lexy(length): yield '' if length > 0: for ch in ['a', 'b', 'c', 'd']: for w in lexy(length - 1): yield ch + w for w in lexy(3): print(w) 26/40

  65. ITERATORS AND GENERATORS Often, for-loops are used to iterate over sequences of elements (stored in a data structure, generated by a procedure, …). Iterators/generators provide a clean idiom for iterating over a sequence without a need to know how the sequence is generated. Generators in Python: def lexy(length): yield '' if length > 0: for ch in ['a', 'b', 'c', 'd']: for w in lexy(length - 1): yield ch + w for w in lexy(3): print(w) 26/40

  66. ITERATORS AND GENERATORS Often, for-loops are used to iterate over sequences of elements (stored in a data structure, generated by a procedure, …). Iterators/generators provide a clean idiom for iterating over a sequence without a need to know how the sequence is generated. Generators in Python: def lexy(length): yield '' if length > 0: for ch in ['a', 'b', 'c', 'd']: for w in lexy(length - 1): yield ch + w for w in lexy(3): print(w) 26/40

  67. ITERATOR OBJECTS C++ and Java provide iterator classes that can be used to enumerate the elements of a collection (or programmatically generate a sequence of elements to be traversed). C++: for (cont::iterator i = cont.begin(); i != cont.end(); ++i) { // Use i } Java 1.4 is similar in its use of the Enumeration interface: Enumeration e = cont.elements(); while (e.hasMoreElements()) { MyObj o = (MyObj) e.nextElement(); // Use o } 27/40

  68. ITERATOR OBJECTS C++ and Java provide iterator classes that can be used to enumerate the elements of a collection (or programmatically generate a sequence of elements to be traversed). C++: for (cont::iterator i = cont.begin(); i != cont.end(); ++i) { // Use i } Java 1.4 is similar in its use of the Enumeration interface: Enumeration e = cont.elements(); while (e.hasMoreElements()) { MyObj o = (MyObj) e.nextElement(); // Use o } 27/40

  69. ITERATOR OBJECTS C++ and Java provide iterator classes that can be used to enumerate the elements of a collection (or programmatically generate a sequence of elements to be traversed). C++: for (cont::iterator i = cont.begin(); i != cont.end(); ++i) { // Use i } Java 1.4 is similar in its use of the Enumeration interface: Enumeration e = cont.elements(); while (e.hasMoreElements()) { MyObj o = (MyObj) e.nextElement(); // Use o } 27/40

  70. TYING ITERATOR OBJECTS TO FOR-LOOPS Many modern languages provide convenient syntax for iterating over sequences generated using iterators. Behind the scenes, this is translated into code that explicitly uses iterator objects. Modern Java (post Java 5): for (MyObj obj : cont) { // Use obj } Modern C++ (post C++11): for (auto &obj : cont) { // Use obj } 28/40

  71. TYING ITERATOR OBJECTS TO FOR-LOOPS Many modern languages provide convenient syntax for iterating over sequences generated using iterators. Behind the scenes, this is translated into code that explicitly uses iterator objects. Modern Java (post Java 5): for (MyObj obj : cont) { // Use obj } Modern C++ (post C++11): for (auto &obj : cont) { // Use obj } 28/40

  72. TYING ITERATOR OBJECTS TO FOR-LOOPS Many modern languages provide convenient syntax for iterating over sequences generated using iterators. Behind the scenes, this is translated into code that explicitly uses iterator objects. Modern Java (post Java 5): for (MyObj obj : cont) { // Use obj } Modern C++ (post C++11): for (auto &obj : cont) { // Use obj } 28/40

  73. ITERATION WITHOUT ITERATORS In languages without iterators/generators (e.g., C), we can simulate iterators using function calls: for (it = begin(coll); it != end(coll); it = next(it)) { /* Do something with *it */ } 29/40

  74. ITERATION IN FUNCTIONAL LANGUAGES Functions being first-class objects allows passing a function to be applied to every element to an “iterator” that traverses the collection. Haskell: doubles = map (* 2) [1 ..] pairs = zip [1 ..] doubles doubles2 = filter even [1 ..] 30/40

  75. RECURSION Every iterative procedure can be turned into a recursive one: while (condition) { S1; S2; ... } becomes procedure P() { if (condition) { S1; S2; ...; P(); } } The converse is not true (e.g., Quicksort, Merge Sort, fast matrix multiplication, …) The type of recursive procedure above can be translated back into a loop by the compiler (tail recursion). 31/40

  76. RECURSION Every iterative procedure can be turned into a recursive one: while (condition) { S1; S2; ... } becomes procedure P() { if (condition) { S1; S2; ...; P(); } } The converse is not true (e.g., Quicksort, Merge Sort, fast matrix multiplication, …) The type of recursive procedure above can be translated back into a loop by the compiler (tail recursion). 31/40

  77. RECURSION Every iterative procedure can be turned into a recursive one: while (condition) { S1; S2; ... } becomes procedure P() { if (condition) { S1; S2; ...; P(); } } The converse is not true (e.g., Quicksort, Merge Sort, fast matrix multiplication, …) The type of recursive procedure above can be translated back into a loop by the compiler (tail recursion). 31/40

  78. APPLICATIVE AND NORMAL-ORDER EVALUATION needed. Normal-order evalutaion is potentially inefficient. Why? How can we avoid this? are side effects. Why? Normal-order evaluation is fine in functional languages but problematic if there • Example: macros in C/C++ needed. structures that are computed as • Useful for infinite or lazy data • The subroutine evaluates them as Applicative-order evaluation subroutine unevaluated. • Arguments are passed to the Normal-order evaluation languages • Default in most programming subroutine call Arguments are evaluated before a 32/40

  79. APPLICATIVE AND NORMAL-ORDER EVALUATION needed. Normal-order evalutaion is potentially inefficient. Why? How can we avoid this? are side effects. Why? Normal-order evaluation is fine in functional languages but problematic if there • Example: macros in C/C++ needed. structures that are computed as • Useful for infinite or lazy data • The subroutine evaluates them as Applicative-order evaluation subroutine unevaluated. • Arguments are passed to the Normal-order evaluation languages • Default in most programming subroutine call Arguments are evaluated before a 32/40

  80. APPLICATIVE AND NORMAL-ORDER EVALUATION needed. Normal-order evalutaion is potentially inefficient. Why? How can we avoid this? are side effects. Why? Normal-order evaluation is fine in functional languages but problematic if there • Example: macros in C/C++ needed. structures that are computed as • Useful for infinite or lazy data • The subroutine evaluates them as Applicative-order evaluation subroutine unevaluated. • Arguments are passed to the Normal-order evaluation languages • Default in most programming subroutine call Arguments are evaluated before a 32/40

Recommend


More recommend