- Concepts of Programming Languages

Strict and Nonstrict Evaluation

Instructor:

Learning Objectives

How much of an expression should be evaluated when computing a result?

  • Perform expression evaluation
  • Perform function calls and function argument evaluation

Strict and Nonstrict Operators

  • A strict construct evaluates all of its operands before it runs
  • Name some strict constructs
    • Arithmetic operators: +, -, *, /, ...
    • Comparison operators: <, <=, ==, !=, ...
    • Bitwise operators: |, &, ~, ^
    • Function calls: f(x,y)

Strict and Nonstrict Operators

  • A strict construct evaluates all of its operands before it runs
  • Name some non-strict constructs
    • e1 && e2 is strict in e1, but not e2, useful e.g., p!=null && p.m()
    • e1 || e2 is strict in e1, but not e2, useful e.g., p==null || p.m()
    • if e1 then e2 else e3 is strict in e1, but not e2 or e3

Conditional Expression

Conditional expression if e1 then e2 else e3

  • Evaluate e1; if true then evaluate e2, else evaluate e3
  1. for i <- 0 to 10 do
  2. var x = 0
  3. var y = 0
  4. val z = (if scala.util.Random.nextInt % 2 == 0
  5. then {x=1; 111}
  6. else {y=2; 222})
  7. println(s"x=$x, y=$y, z=$z")
    1. x=0, y=2, z=222
    2. x=1, y=0, z=111
    3. x=1, y=0, z=111
    4. ...

Conditionals in C

  • Conditional statement vs conditional expression
  1. int fact (int n) {
  2. if (n <= 1) {
  3. return 1;
  4. } else {
  5. return n * fact (n - 1);
  6. }
  7. }
  1. int fact (int n) {
  2. return (n <= 1) ? 1 : n * fact (n - 1);
  3. }

What Happens?

  • Function calls are strict
  1. def fcond(b: Boolean, t: Int, f: Int) : Int =
  2. if b then t else f
  3. for i <- 1 to 10 do
  4. var x = 0
  5. var y = 0
  6. val z = fcond(scala.util.Random.nextInt % 2 == 0,
  7. {x=1; 111},
  8. {y=2; 222})
  9. println(s"x=$x, y=$y, z=$z")
    1. x=1, y=2, z=222
    2. x=1, y=2, z=111
    3. x=1, y=2, z=111
    4. ...

What Happens?

  • Thunks: pass-by-name for explicit nonstrict evaluation of function arguments
  1. def fcond(b: Boolean, t: => Int, f: => Int) : Int =
  2. if b then t else f
  3. for i <- 1 to 10 do
  4. var x = 0
  5. var y = 0
  6. val z = fcond(scala.util.Random.nextInt % 2 == 0,
  7. {x=1; 111},
  8. {y=2; 222})
  9. println(s"x=$x, y=$y, z=$z")
    1. x=1, y=0, z=111
    2. x=0, y=2, z=222
    3. x=0, y=2, z=222
    4. ...

Summary

Strict Evaluation

  • Evaluates all operands to determine value of an expression
    • Arithmetic operators etc.
    • Function arguments

Nonstrict Evaluation

  • Evaluates only necessary operands to determine value
    • Conditional expression
    • Shortcut evaluation of boolean expressions
  • Thunks: request explicit nonstrict evaluation of function arguments