About SICP The following Scala code is derived from the examples provided in the book:
      "Structure and Interpretation of Computer Programs, Second Edition" by Harold Abelson and Gerald Jay Sussman with Julie Sussman.
      http://mitpress.mit.edu/sicp/

SICP Chapter #01 Examples in Scala

object SICP01 {
   def main(args: Array[String]): unit = {

      /* 1.1.1 The Elements of Programming - Expressions */
      486;
      137 + 349;
      1000 - 334;
      5 * 99;
      10 / 5;
      2.7 + 10.0;
      21 + 35 + 12 + 7;
      25 * 4 * 12;
      (3 * 5) + (10 - 6);
      (3 * ((2 * 4) + (3 + 5))) + ((10 - 7) + 6);

      /* 1.1.2 The Elements of Programming - Naming and the Environment */
      val size = 2;
      size;
      5 * size;
      val pi = 3.14159;
      val radius = 10.0;
      pi * radius * radius;
      val circumference = 2.0 * pi * radius;
      circumference;

      /* 1.1.3 The Elements of Programming - Evaluating Combinations */
      (2 + (4 * 6)) * (3 + 5 + 7);

      /* 1.1.4 The Elements of Programming - Compound Procedures */
      def square(x: long) = x * x;
      square(21);
      square(2 + 5);
      square(square(3));
      def sum_of_squares(x: long, y: long) = square(x) + square(y);
      sum_of_squares(3, 4);
      def f(a: long) = sum_of_squares(a + 1, a * 2);
      f(5);

      /* 1.1.5 The Elements of Programming - The Substitution Model for Procedure Application */
      f(5);
      sum_of_squares(5 + 1, 5 * 2);
      square(6) + square(10);
      (6 * 6) + (10 * 10);
      36 + 100;
      f(5);
      sum_of_squares(5 + 1, 5 * 2);
      (square(5 + 1)) + (square(5 * 2));

      ((5 + 1) * (5 + 1)) + ((5 * 2) * (5 * 2));
      (6 * 6) + (10 * 10);
      36 + 100;
      136;

      /* 1.1.6 The Elements of Programming - Conditional Expressions and Predicates */
      def abs(x: long) =
         if (x > 0)
            x
            else if (x == 0) 0
            else -x;
      def abs_1(x: long) =
         if (x < 0)
            -x
            else x
      val x = 6;
      (x > 5) && (x < 10);
      def ge(x: long, y: long) =
         (x > y) || (x == y);
      def ge_1(x: long, y: long) =
         !(x < y);

      /* Exercise 1.1 */
      10;
      5 + 3 + 4;
      9 - 1;
      6 / 2;
      (2 * 4) + (4 - 6);
      val a = 3;
      val b = a + 1;
      a + b + (a * b);
      (a == b);
      if ((b > a) && (b < (a *b)))
         b
         else a;
      if (a == 4)
         6
         else if (b == 4) 6 + 7 + a
         else 25;
      2 + (if (b > a) b else a);
      (if (a > b)
         a
         else if (a < b) b
         else -1) * (a + 1);

      /* Exercise 1.2 */
      (5.0 + 4.0 + (2.0 - (3.0 - (6.0 + (4.0 / 5.0))))) /
         (3.0 * (6.0 - 2.0) * (2.0 - 7.0));

      /* Exercise 1.4 */
      def a_plus_abs_b(a: long, b: long) =
         if (b > 0)
            a + b
            else a - b;

      /* Exercise 1.5 */
      def p(): Unit = p();
      def test(x: long, y: long) =
         if (x == 0)
            0
            else y;
      /* commented out as this is in infinite loop
         test(0, p());
      */

      /* 1.1.7 The Elements of Programming - Example: Square Roots by Newton's Method */
      def square_double(x: double) = x * x;
      def abs_double (x: double) = if (x < 0) -x else x

      def good_enough(guess: double, x: double) =
         abs_double(square_double(guess) - x) < 0.001;

      def average(x: double, y: double) =
         (x + y) / 2.0;

      def improve(guess: double, x: double) =
         average(guess, x / guess);

      def sqrt_iter(guess: double, x: double): double =
         if (good_enough(guess, x))
            guess
            else sqrt_iter(improve(guess, x), x);

      def sqrt(x: double) =
         sqrt_iter(1.0, x);

      sqrt(9.0);
      sqrt(100.0 + 37.0);
      sqrt((sqrt(2.0))+(sqrt(3.0)));
      square_double(sqrt(1000.0));

      /* Exercise 1.6 */
      def new_if(predicate: boolean, then_clause: double, else_clause: double) =
         if (predicate)
            then_clause
            else else_clause;
      new_if((2==3), 0, 5);
      new_if((1==1), 0, 5);
      def sqrt_iter_(guess: double, x: double): double =
         new_if(
            good_enough(guess, x),
            guess,
            sqrt_iter_(improve(guess, x), x));

      /* 1.1.8 The Elements of Programming - Procedures as Black-Box Abstractions */
      def square_double_1(x: double) = x * x;

      def doublex(x: double) = x + x;

      def square_double_2(x: double) = Math.exp(doublex(Math.log(x)));

      def good_enough_1(guess: double, x: double) =
         abs_double((square_double_2(guess)) - x) < 0.001;

      def improve_1(guess: double, x: double) =
         average(guess, x / guess);

      def sqrt_iter_1(guess: double, x: double): double =
         if (good_enough(guess, x))
            guess
            else sqrt_iter_1(improve_1(guess, x), x);

      def sqrt_1(x: double) =
         sqrt_iter_1(1.0, x);

      square_double_1(5.0);

      // Block-structured
      def sqrt_2(x: double) =
      {
         def good_enough(guess: double, x: double) =
            abs_double(square_double(guess) - x) < 0.001;

         def improve(guess: double, x: double) =
            average(guess, x / guess);

         def sqrt_iter(guess: double, x: double): double =
            if (good_enough(guess, x))
               guess
               else sqrt_iter(improve(guess, x), x)

         sqrt_iter(1.0, x);
      };

      // Taking advantage of lexical scoping
      def sqrt_3(x: double) = {
         def good_enough(guess: double) =
            abs_double(square_double(guess) - x) < 0.001;

         def improve(guess: double) =
            average(guess, x / guess);

         def sqrt_iter(guess: double): double =
            if (good_enough(guess))
               guess
               else sqrt_iter(improve(guess));

         sqrt_iter(1.0);
      };

      /* 1.2.1 Procedures and the Processes They Generate - Linear Recursion and Iteration */

      // Recursive
      def factorial(n: long): long =
         if (n == 1)
            1
            else n * factorial(n - 1);

      // Iterative
      def fact_iter(product: long, counter: long, max_count: long): long =
         if (counter > max_count)
            product
            else fact_iter(counter * product, counter + 1, max_count);

      def factorial_1(n: long) =
         fact_iter(1, 1, n);

      // Iterative, block-structured (from footnote)
      def factorial_2(n: long) = {
         def iter(product: long, counter: long): long =
            if (counter > n)
               product
               else iter(counter * product, counter + 1);

         iter(1, 1);
      };

      /* Exercise 1.9 */
      def inc(a: long) = a + 1;
      def dec(a: long) = a - 1;
      def plus(a: long, b: long) =
         if (a == 0)
            b
            else inc(dec(a) + b);
      def plus_1(a: long, b: long) =
         if (a == 0)
            b
            else dec(a) + inc(b);

      /* Exercise 1.10 */
      def a_(x: long, y: long): long =
         Pair(x, y) match {
            case Pair(x, 0) => 0;
            case Pair(0, y) => 2 * y;
            case Pair(x, 1) => 2;
            case Pair(x, y) => a_(x - 1, a_(x, y - 1));
         };
      a_(1, 10);
      a_(2, 4);
      a_(3, 3);
      def f_(n: long) = a_(0, n);
      def g_(n: long) = a_(1, n);
      def h_(n: long) = a_(2, n);
      def k_(n: long) = 5 * n * n;

      /* 1.2.2 Procedures and the Processes They Generate - Tree Recursion */

      // Recursive
      def fib(n: long): long =
         n match {
            case 0 => 0;
            case 1 => 1;
            case n => fib(n - 1) + fib(n - 2);
         };

      // Iterative
      def fib_iter(a: long, b: long, count: long): long =
         count match {
            case 0 => b;
            case count => fib_iter(a + b, a, count - 1);
         }
      def fib_1(n: long) =
         fib_iter(1, 0, n);

      // Counting change
      def first_denomination(x: long) =
         x match {
            case 1 => 1;
            case 2 => 5;
            case 3 => 10;
            case 4 => 25;
            case 5 => 50;
            case x => throw new Exception("Domain");
         };

      def cc(amount: long, kinds_of_coins: long): long =
         if (amount == 0)
            1
            else if (amount < 0) 0
            else if (kinds_of_coins == 0) 0
            else cc(amount, kinds_of_coins - 1) +
                 cc(amount - first_denomination(kinds_of_coins), kinds_of_coins);

      def count_change(amount: long) =
         cc(amount, 5);

      count_change(100);

      /* Exercise 1.11 */
      def fi(n: long): long =
         if (n < 3)
            n;
            else fi(n - 1) + 2 * fi(n - 2) + 3 * fi(n - 3);

      def fi_iter(a: long, b: long, c: long, count: long): long =
         if (count == 0)
            c;
            else fi_iter(a + 2 * b + 3 * c, a, b, count - 1);

      def fi_1(n: long): long = fi_iter(2, 1, 0, n);

      /* Exercise 1.12 */
      def pascals_triangle(n: long, k: long): long =
         if (n == 0 || k == 0 || n == k)
            1;
            else pascals_triangle(n - 1, k - 1) + pascals_triangle(n - 1, k);

      /* 1.2.3 Procedures and the Processes They Generate - Orders of Growth */
      /* Exercise 1.15 */
      def cube_double(x:double) = x * x * x;
      def p_(x: double) = (3.0 * x) - (4.0 * cube_double(x));
      def sine(angle: double): double =
         if (!(abs_double(angle) > 0.1))
            angle
            else p_(sine(angle / 3.0));

      /* 1.2.4 Procedures and the Processes They Generate - Exponentiation */

      // Linear recursion
      def expt(b: long, n: long): long =
         n match {
            case 0 => 1;
            case n => b * expt(b, (n - 1));
         };

      // Linear iteration
      def expt_iter(b: long, counter: long, product: long): long =
         counter match {
            case 0 => product;
            case counter => expt_iter(b, counter - 1, b * product);
         };
      def expt_1(b: long, n: long) =
         expt_iter(b, n, 1);

      // Logarithmic iteration
      def even(n: long) = ((n % 2) == 0);

      def fast_expt(b: long, n: long): long =
         n match {
            case 0 => 1;
            case n =>
               if (even(n))
                  square(fast_expt(b, n / 2))
                  else b * fast_expt(b, n - 1);
         };

      /* Exercise 1.17 */
      def multiply(a: long, b: long) =
         b match {
            case 0 => 0;
            case b => a + (a * (b - 1));
         };

      /* Exercise 1.19 */
      /* exercise left to reader to solve for p' and q'
         def fib_iter_(a: long, b: long, p: long, q: long, count: long): long =
            count match {
               case 0 => b;
               case count =>
                  if (even(count))
                     fib_iter_(a, b, p', q', count / 2);
                     else fib_iter_((b * q) + (a * q) + (a * p), (b * p) + (a * q), p, q, count - 1);
            };
         def fib_2(n: long) =
            fib_iter_(1, 0, 0, 1, n);
      */

      /* 1.2.5 Procedures and the Processes They Generate - Greatest Common Divisors */
      def gcd(a: long, b: long): long =
         b match {
            case 0 => a;
            case b => gcd(b, a % b);
         };

      /* 1.2.6 Procedures and the Processes They Generate - Example: Testing for Primality */

      // prime
      def divides(a: long, b: long) = ((b % a) == 0);

      def find_divisor(n: long, test_divisor: long): long =
         if (square(test_divisor) > n)
            n
            else if (divides(test_divisor, n)) test_divisor
            else find_divisor(n, test_divisor + 1);

      def smallest_divisor(n: long) = find_divisor(n, 2);

      def prime(n: long) = (n == smallest_divisor(n));

      // fast_prime
      def expmod(nbase: long, nexp: long, m: long): long =
         nexp match {
            case 0 => 1;
            case nexp =>
               if (even(nexp))
                  square(expmod(nbase, nexp / 2, m)) % m
                  else (nbase * (expmod(nbase, (nexp - 1), m))) % m;
         };

      def fermat_test(n: long) = {
         def try_it(a: long) = (expmod(a, n, n) == a)
            true; //CMR         try_it(1 + Math.round(Math.random() * (n - 1)));
      };

      def fast_prime(n: long, ntimes: long): boolean =
         ntimes match {
            case 0 => true;
            case ntimes =>
               if (fermat_test(n))
                  fast_prime(n, ntimes - 1)
                  else false;
         };

      /* Exercise 1.22 */
      def report_prime(elapsed_time: long) =
         System.out.println(" *** " + elapsed_time);
      def start_prime_test(n: long, start_time: long) =
         if (prime(n))
            report_prime(java.util.Calendar.getInstance().get(java.util.Calendar.MILLISECOND) - start_time)
            else ();
      def timed_prime_test(n: long) = {
         System.out.println(n);
         start_prime_test(n, java.util.Calendar.getInstance().get(java.util.Calendar.MILLISECOND));
      };

      /* Exercise 1.25 */
      def expmod_(nbase: long, nexp: long, m: long) =
         fast_expt(nbase, nexp) % m;

      /* Exercise 1.26 */
      def expmod_2(nbase: long, nexp: long, m: long): long =
         nexp match {
            case 0 => 1;
            case nexp =>
               if (even(nexp))
                  (expmod_2(nbase, (nexp / 2), m) * expmod_2(nbase, (nexp / 2), m)) % m
                  else (nbase * expmod_2(nbase, nexp - 1, m)) % m;
         };

      /* 1.3 Formulating Abstractions with Higher-Order Procedures */
      def cube(x: long) = x * x * x;

      /* 1.3.1 Formulating Abstractions with Higher-Order Procedures - Procedures as Arguments */
      def sum_integers(a: long, b: long): long =
         if (a > b)
            0
            else a + sum_integers(a + 1, b);

      def sum_cubes(a: long, b: long): long =
         if (a > b)
            0
            else cube(a) + sum_cubes(a + 1, b);

      def pi_sum(a: double, b: double): double =
         if (a > b)
            0.0
            else (1.0 / (a * (a + 2.0))) + pi_sum(a + 4.0, b);

      def sum(term: long=>long, a: long, next: long=>long, b: long): long =
         if (a > b)
            0
            else term(a) + sum(term, next(a), next, b);

      // Using sum
      def inc_(n:long) = n + 1;

      def sum_cubes_(a: long, b: long) =
         sum(cube, a, inc_, b);

      sum_cubes_(1, 10);

      def identity(x: long) = x

      def sum_integers_(a: long, b: long) =
         sum(identity, a, inc_, b);

      sum_integers_(1, 10);

      def sum_double(term: double=>double, a: double, next: double=>double, b: double): double =
         if (a > b)
            0.0
            else term(a) + sum_double(term, next(a), next, b: double);

      def pi_sum_(a: double, b: double) = {
         def pi_term(x: double) = 1.0 / (x * (x + 2.0))
         def pi_next(x: double) = x + 4.0
         sum_double(pi_term, a, pi_next, b)
      };

      8.0 * pi_sum_(1.0, 1000.0);

      def integral(f: double=>double, a: double, b: double, dx: double) = {
         def add_dx(x: double) = x + dx
         sum_double(f, a + (dx / 2.0), add_dx, b) * dx
      };

      def cube_double_(x: double) = x * x * x;

      integral(cube_double_, 0.0, 1.0, 0.01);
      integral(cube_double_, 0.0, 1.0, 0.001);

      /* Exercise 1.29 */
      def simpson(f: double => double, a: double, b: double, n: long) = {
         val h = Math.abs(b - a) / n;

          def sum_iter(term: double => double, start: long, next: long => long, stop: long, acc: double): double =
             if (start > stop)
                acc;
                else sum_iter(term, next(start), next, stop, acc + term(a + start * h));

         h * sum_iter(f, 1, inc_, n, 0.0);
      }

      simpson(cube_double_, 0.0, 1.0, 100);

      /* Exercise 1.30 */
      def sum_iter(term: long => long, a: long, next: long => long, b: long, acc: long): long =
         if (a > b)
            acc;
            else sum_iter(term, next(a), next, b, acc + term(a));

      // 'sum_cubes_2' reimplements 'sum_cubes_' but uses 'sum_iter' in place of 'sum'
      def sum_cubes_2(a: long, b: long): long = sum_iter(cube, a, inc, b, 0);

      sum_cubes_2(1, 10);

      /* Exercise 1.31 */
      // a.
      def product(term: long => long, a: long, next: long => long, b: long): long =
         if (a > b)
            1;
            else term(a) * product(term, next(a), next, b);

      def factorial_3(n: long) = product(identity, 1, inc, n);

      // b.
      def product_iter(term: long => long, a: long, next: long => long, b: long, acc: long): long =
         if (a > b)
            acc;
            else product_iter(term, next(a), next, b, acc * term(a));

      def factorial_4(n: long) = product_iter(identity, 1, inc, n, 1);

      /* Exercise 1.32 */
      // a.
      def accumulate(combiner: (long, long) => long, nullValue: long, term: long => long, a: long, next: long => long, b: long): long =
         if (a > b)
            nullValue;
            else combiner(term(a), accumulate(combiner, nullValue, term, next(a), next, b));

      // sum:     accumulate(plus, 0, identity, a, inc, b);
      // product: accumulate(times, 1, identity, a, inc, b);

      // b.
      // NOTE: starting value of 'acc' is 'nullValue'
      def accumulate_iter(combiner: (long, long) => long, term: long => long, a: long, next: long => long, b: long, acc: long): long =
         if (a > b)
            acc;
            else accumulate_iter(combiner, term, next(a), next, b, combiner(acc, term(a)));

      // sum:     accumulate_iter(plus, identity, a, inc, b, 0);
      // product: accumulate_iter(times, identity, a, inc, b, 1);

      /* Exercise 1.33 */
      def filtered_accumulate(combiner: (long, long) => long, nullValue: long, term: long => long, a: long, next: long => long, b: long, pred: long => boolean): long =
         if (a > b)
            nullValue;
            else if (pred(a))
               combiner(term(a), filtered_accumulate(combiner, nullValue, term, next(a), next, b, pred));
               else filtered_accumulate(combiner, nullValue, term, next(a), next, b, pred);

      // a.
      filtered_accumulate(plus, 0, square, 1, inc, 5, prime);  // 39

      // b. Not sure how to implement this without modifying 'filtered_accumulate' to have 'pred'
      //    accept two arguments

      /* 1.3.2 Formulating Abstractions with Higher-Order Procedures - Constructing Procedures Using Lambda */
      def pi_sum_2(a: double, b: double) =
        sum_double((x: double) => 1.0 / (x * (x + 2.0)), a, (x: double) => x + 4.0, b);

      def integral_(f: double=>double, a: double, b: double, dx: double) =
         sum_double(f, a + (dx / 2.0), (x: double) => x + dx, b) * dx;

      def plus4(x: long) = x + 4;

      val plus4_1 = (x: long) => x + 4;

      ((x: long, y: long, z: long) => x + y + square(z))(1, 2, 3);

      // Using let
      def f_2(x: long, y: long) = {
         def f_helper(a: long, b: long) =
            (x * square(a)) + (y * b) + (a * b);
         f_helper(1 + (x * y), 1 - y)
      };

      def f_3(x: long, y: long) =
         (((a: long, b: long) => ((x * square(a)) + (y * b) + (a * b)))
            (1 + (x * y), 1 - y));

      def f_4(x: long, y: long) = {
         val a = 1 + (x * y);
         val b = 1 - y;
         (x * square(a)) + (y * b) + (a * b);
      };

      val x_1 = 5;
      {
         val x_1 = 3;
         x_1 + (x_1 * 10);
      } + x_1;

      val x_2 = 2;
      {
         val y = x_2 + 2;
         {
            val x_2 = 3;
            x_2 * y;
         };
      };

      def f_5(x: long, y: long) = {
         val a = 1 + (x * y);
         val b = 1 - y;
         (x * square(a)) + (y * b) + (a * b);
      };

      /* Exercise 1.34 */
      def f_6(g: long=>long) = g(2);
      f_6(square);
      f_6((z: long) => z * (z + 1));

      /* 1.3.3 Formulating Abstractions with Higher-Order Procedures - Procedures as General Methods */

      // Half-interval method
      def close_enough(x: double, y: double) =
         (abs_double(x - y) < 0.001);

      def positive(x: double) = (x >= 0.0);
      def negative(x: double) = !positive(x);

      def search(f: double=>double, neg_point: double, pos_point: double): double = {
         val midpoint = average(neg_point, pos_point);
         if (close_enough(neg_point, pos_point))
            midpoint
            else {
               val test_value = f(midpoint);
               if (positive(test_value))
                  search(f, neg_point, midpoint)
                  else if (negative(test_value)) search(f, midpoint, pos_point)
                  else midpoint;
            };
      };

      def half_interval_method(f: double=>double, a: double, b: double) = {
         val a_value = f(a);
         val b_value = f(b);
         if (negative(a_value) && positive(b_value))
            search(f, a, b)
            else if (negative(b_value) && positive(a_value)) search(f, b, a)
            else throw new Exception("Values are not of opposite sign" + a + " " + b);
      };

      half_interval_method(Math.sin, 2.0, 4.0);

      half_interval_method((x: double) => (x * x * x) - (2.0 * x) - 3.0, 1.0, 2.0);

      // Fixed points
      val tolerance = 0.00001;

      def fixed_point(f: double=>double, first_guess: double) = {
         def close_enough(v1: double, v2: double) =
            abs_double(v1 - v2) < tolerance;
         def try_(guess: double): double = {
            val next = f(guess);
            if (close_enough(guess, next))
               next
               else try_(next);
         }
         try_(first_guess);
      };

      fixed_point(Math.cos, 1.0);

      fixed_point((y: double) => Math.sin(y) + Math.cos(y), 1.0);

      def sqrt_4(x: double) =
         fixed_point((y : double) => x / y, 1.0)

      def sqrt_5(x: double) =
         fixed_point((y: double) => average(y, x / y), 1.0);

      /* Exercise 1.35 */
      def golden_ratio() =
         fixed_point((x: double) => 1.0 + 1.0 / x, 1.0);

      /* Exercise 1.36 */
      // Add the following line to function, 'fixed-point':
      //  ... val next = f(guess);
      //  System.out.println(next);
      //  ... if (close_enough(guess, next))

      fixed_point((x: double) => Math.log(1000.0) / Math.log(x), 1.5);
      fixed_point(average_damp((x: double) => Math.log(1000.0) / Math.log(x)), 1.5);

      /* Exercise 1.37 */
      /* exercise left to reader to define cont_frac
         cont_frac((i: double) => 1.0, (i: double) => 1.0, k);
      */

      /* Exercise 1.38 - unfinished */

      /* Exercise 1.39 - unfinished */

      /* 1.3.4 Formulating Abstractions with Higher-Order Procedures - Procedures as Returned Values */
      def average_damp(f: double=>double) =
         (x: double) => average(x, f(x));

      (average_damp(square_double))(10.0);

      def sqrt_6(x: double) =
         fixed_point(average_damp((y: double) => x / y), 1.0);

      def cube_root(x: double) =
         fixed_point(average_damp((y: double) => x / square_double(y)), 1.0);

      // Newton's method
      val dx = 0.00001;
      def deriv(g: double=>double) =
         (x: double) => (g(x + dx) - g(x)) / dx;

      def cube_1(x: double) = x * x * x;

      def newton_transform(g: double=>double) =
         (x: double) => x - (g(x) / (deriv(g)(x)));

      def newtons_method(g: double=>double, guess: double) =
         fixed_point(newton_transform(g), guess);

      def sqrt_7(x: double) =
         newtons_method((y: double) => square_double(y) - x, 1.0);

      // Fixed point of transformed function
      def fixed_point_of_transform(g: double=>double, transform: (double=>double)=>(double=>double), guess: double) =
         fixed_point(transform(g), guess);

      def sqrt_8(x: double) =
         fixed_point_of_transform((y: double) => x / y, average_damp, 1.0);

      def sqrt_9(x: double) =
         fixed_point_of_transform((y: double) => square_double(y) - x,  newton_transform, 1.0);

      /* Exercise 1.40 */
      def cubic(a: double, b: double, c: double): (double => double) =
         (x: double) => x * x * x + a * x * x + b * x + c;

      newtons_method(cubic(5.0, 3.0, 2.5), 1.0); // -4.452...

      /* Exercise 1.41 */
      def double_(f: long => long) =
         (x: long) => f(f(x));

      (double_(inc))(5);                         //  7
      (double_(double_(inc)))(5);                //  9
      (double_(double_(double_(inc))))(5);       // 13

      /* Exercise 1.42 */
      def compose_(f: long => long, g: long => long) =
         (x: long) => f(g(x));

      (compose_(square, inc))(6);                // 49

      /* Exercise 1.43 */
      def repeated(f: long => long, n: long) = {
         def iterate(arg: long, i: long): long =
            if (i > n)
               arg;
               else iterate(f(arg), i + 1);

         (x: long) => iterate(x, 1);
      }

      (repeated(square, 2))(5);                  // 625

      /* Exercise 1.44 ('n-fold-smooth' not implemented) */
      def smooth(f: double => double, dx: double) =
         (x: double) => average(x, (f(x - dx) + f(x) + f(x + dx)) / 3.0);

      fixed_point(smooth((x: double) => Math.log(1000.0) / Math.log(x), 0.05), 1.5);

      /* Exercise 1.45 - unfinished */

      /* Exercise 1.46 ('sqrt' not implemented) */
      def iterative_improve(good_enough: (double, double) => boolean, improve: double => double) = {
         def iterate(guess: double): double = {
            val next = improve(guess);
            if (good_enough(guess, next))
               next;
               else iterate(next);
         }

         (x: double) => iterate(x);
      }

      def fixed_point_(f: double => double, first_guess: double) = {
         val tolerance = 0.00001;

         def good_enough(v1: double, v2: double) =
            abs_double(v1 - v2) < tolerance;

         (iterative_improve(good_enough, f))(first_guess);
      }

      fixed_point_(average_damp((x: double) => Math.log(1000.0) / Math.log(x)), 1.5);
   }
}

Chris Rathman / Chris.Rathman@tx.rr.com