About SICP The following Oz 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 Oz
% 1.1.1 The Elements of Programming - Expressions
{Browse 486}
{Browse 137 + 349}
{Browse 1000 - 334}
{Browse 5 * 99}
{Browse 10 div 5}
{Browse 2.7 + 10.0}
{Browse 21 + 35 + 12 + 7}
{Browse 25 * 4 * 12}
{Browse 3 * 5 + 10 - 6}
{Browse 3 * (2 * 4 + 3 + 5) + 10 - 7 + 6}

% 1.1.2 The Elements of Programming - Naming and the Environment
Size = 2
{Browse Size}
{Browse 5 * Size}
Pi = 3.14159
Radius = 10.0
{Browse Pi * Radius * Radius}
Circumference = 2.0 * Pi * Radius
{Browse Circumference}

% 1.1.3 The Elements of Programming - Evaluating Combinations
{Browse (2 + 4 * 6) * (3 + 5 + 7)}

% 1.1.4 The Elements of Programming - Compound Procedures
fun {Square X} X * X end
{Browse {Square 21}}
{Browse {Square 2 + 5}}
{Browse {Square {Square 3}}}
fun {Sum_of_Squares X Y} {Square X} + {Square Y} end
{Browse {Sum_of_Squares 3 4}}
fun {F A} {Sum_of_Squares A+1 A*2} end
{Browse {F 5}}

% 1.1.5 The Elements of Programming - The Substitution Model for Procedure Application
{Browse {F 5}}
{Browse {Sum_of_Squares 5+1 5*2}}
{Browse {Square 6} + {Square 10}}
{Browse 6*6 + 10*10}
{Browse 36 + 100}
{Browse {F 5}}
{Browse {Sum_of_Squares 5+1 5*2}}
{Browse {Square 5+1} + {Square 5*2}}

{Browse ((5 + 1) * (5 + 1)) + ((5 * 2) * (5 * 2))}
{Browse (6 * 6) + (10 * 10)}
{Browse 36 + 100}
{Browse 136}

% 1.1.6 The Elements of Programming - Conditional Expressions and Predicates
fun {Abs X}
   if {IsInt X} then
      if X > 0 then
         X
      elseif X == 0 then
         0
      else
         ~X
      end
   elseif {IsFloat X} then
      if X > 0.0 then
         X
      elseif X == 0.0 then
         0.0
      else
         ~X
      end
   end
end

fun {Abs_1 X}
   if {IsInt X} then
      if X < 0 then
         ~X
      else
         X
      end
   elseif {IsFloat X} then
      if X < 0.0 then
         ~X
      else
         X
      end
   end
end

X = 6
{Browse X > 5 andthen X < 10}

fun {GE X Y}
   x > y orelse x == y
end
fun {GE_1 X Y}
   {Not X < Y}
end

% Exercise 1.1
{Browse 10}
{Browse 5 + 3 + 4}
{Browse 9 - 1}
{Browse 6 div 2}
{Browse 2*4 + 4 - 6}
A = 3
B = A + 1
{Browse A + B + A*B}
{Browse A == B}
{Browse
   if B > A andthen B < A * B then
      B
   else
      A
   end}
{Browse
   if A == 4 then
      6
   elseif B == 4 then
      6 + 7 + A
   else
      25
   end}
{Browse 2 + if B > A then B else A end}
{Browse
   if A > B then
      A
   elseif A < B then
      B
   else
      ~1
   end * (A + 1)}

% Exercise 1.2
% Note: Oz does not have built in rational types, so we'll cheat and do it in floating point
{Browse (5.0 + 4.0 + (2.0 - (3.0 - (6.0 + 4.0/5.0)))) /
        (3.0 * (6.0 - 2.0) * (2.0 - 7.0))}

% Note: The question asks for prefix form
{Browse {Float.'/' {Number.'+' 5.0 {Number.'+' 4.0 {Number.'-' 2.0 {Number.'-' 3.0 {Number.'+' 6.0 {Float.'/' 4.0 5.0}}}}}}
                   {Number.'*' 3.0 {Number.'*' {Number.'-' 6.0 2.0} {Number.'-' 2.0 7.0}}}}}

% Note: To do rationals properly, we need some stuff from chapter 2
RATIONAL =
   functor
   export
      make : Make
      imake : IMake
      '+' : AddRat
      '-' : SubRat
      '*' : MulRat
      '/' : DivRat
   define
      fun {Gcd A B} if B == 0 then A else {Gcd B (A mod B)} end end
      fun {Make N D} G = {Abs {Gcd N D}} in rational(if D >= 0 then N else ~N end div G {Abs D} div G) end
      fun {IMake N} {Make N 1} end
      fun {Numer rational(N D)} N end
      fun {Denom rational(N D)} D end
      fun {AddRat X Y} {Make {Numer X}*{Denom Y} + {Numer Y}*{Denom X} {Denom X}*{Denom Y}} end
      fun {SubRat X Y} {Make {Numer X}*{Denom Y} - {Numer Y}*{Denom X} {Denom X}*{Denom Y}} end
      fun {MulRat X Y} {Make {Numer X}*{Numer Y} {Denom X}*{Denom Y}} end
      fun {DivRat X Y} {Make {Numer X}*{Denom Y} {Denom X}*{Numer Y}} end
   end
[Rational] = {Module.apply [RATIONAL]}

{Browse {Rational.'/' {Rational.'+' {Rational.imake 5} {Rational.'+' {Rational.imake 4} {Rational.'-' {Rational.imake 2} {Rational.'-' {Rational.imake 3} {Rational.'+' {Rational.imake 6} {Rational.make 4 5}}}}}}
                      {Rational.imake 3 * (6 - 2) * (2 - 7) }}}

% Exercise 1.3
fun {SumSquareMax A B C}
   if A > B then
      if A > C then
         if B > C then
            A*A + B*B
         else
            A*A + C*C
         end
      else
         A*A + C*C
      end
   else
      if B > C then
         if A > C then
            B*B + A*A
         else
            B*B + C*C
         end
      else
         B*B + C*C
      end
   end
end

% or more concisely
fun {SumSquareMax_1 A B C}
   X#Y = if A > B then A#B else B#A end
   Z = if Y > C then Y else C end
in
  X*X + Z*Z
end

% Exercise 1.4
fun {A_Plus_Abs_B A B}
   {if B > 0 then Number.'+' else Number.'-' end A B}
end

% Exercise 1.5
fun {P} {P} end
fun {Test X Y}
   if X == 0 then
      0
   else
      Y
   end
end
% commented out as this is in infinite loop
% {Browse {Test 0 {P}}}

% 1.1.7 The Elements of Programming - Example: Square Roots by Newton's Method
fun {GoodEnough Guess X}
   {Abs {Square Guess} - X} < 0.001
end

fun {Average X Y}
   (X + Y) / 2.0
end

fun {Improve Guess X}
   {Average Guess X/Guess}
end

fun {SqrtIter Guess X}
   if {GoodEnough Guess X} then
      Guess
   else
      {SqrtIter {Improve Guess X} X}
   end
end

fun {Sqrt_0 X}
   {SqrtIter 1.0 X}
end

{Browse {Sqrt_0 9.0}}
{Browse {Sqrt_0 100.0 + 37.0}}
{Browse {Sqrt_0 {Sqrt_0 2.0}+{Sqrt_0 3.0}}}
{Browse {Square {Sqrt_0 1000.0}}}

% Exercise 1.6
fun {NewIf Predicate ThenClause ElseClause}
   case Predicate
   of true then ThenClause
   else ElseClause
   end
end

{Browse {NewIf 2==3 0 5}}
{Browse {NewIf 1==1 0 5}}

fun {SqrtIterNewIf Guess X}
   {NewIf {GoodEnough Guess X}
      Guess
      {SqrtIterNewIf {Improve Guess X} X}}
end

fun {SqrtNewIf X}
   {SqrtIterNewIf 1.0 X}
end
% commented out as this is in infinite loop
% {Browse {SqrtNewIf 9.0}}

% Exercise 1.7
fun {GoodEnoughGP Guess Prev}
   {Abs Guess-Prev} / Guess < 0.001
end

fun {SqrtIterGP Guess Prev X}
   if {GoodEnoughGP Guess Prev} then
      Guess
   else
      {SqrtIterGP {Improve Guess X} Guess X}
   end
end

fun {SqrtGP X}
   {SqrtIterGP 4.0 1.0 X}
end

% Exercise 1.8
fun {ImproveCube Guess X}
   (2.0*Guess + X/(Guess * Guess)) / 3.0
end

fun {CubeIter Guess Prev X}
   if {GoodEnoughGP Guess Prev} then
      Guess
   else
      {CubeIter {ImproveCube Guess X} Guess X}
   end
end

fun {CubeRoot_0 X}
   {CubeIter 27.0 1.0 X}
end

% 1.1.8 The Elements of Programming - Procedures as Black-Box Abstractions
% Same as above
% fun {Square X} X * X end

fun {Double X} X + X end

fun {Square_1 X} {Exp {Double {Log X}}} end

fun {GoodEnough_1 Guess X}
   {Abs {Square Guess}-X} < 0.001
end

fun {Improve_1 Guess X}
   {Average Guess X/Guess}
end

fun {SqrtIter_1 Guess X}
   if {GoodEnough_1 Guess X} then
      Guess
   else
      {SqrtIter_1 {Improve_1 Guess x} X}
   end
end

fun {Sqrt_1 X}
   {SqrtIter_1 1.0 X}
end

{Browse {Square 5.0}}

% Block-structured
fun {Sqrt_2 X}
   fun {GoodEnough Guess X}
      {Abs {Square Guess}-X} < 0.001
   end
   fun {Improve Guess X}
      {Average Guess X/Guess}
   end
   fun {SqrtIter Guess X}
      if {GoodEnough Guess X} then
         Guess
      else
         {SqrtIter {Improve Guess X} X}
      end
   end
in
   {SqrtIter 1.0 X}
end

% Taking advantage of lexical scoping
fun {Sqrt_3 X}
   fun {GoodEnough Guess}
      {Abs {Square Guess}-X} < 0.001
   end
   fun {Improve Guess}
      {Average Guess X/Guess}
   end
   fun {SqrtIter Guess}
      if {GoodEnough Guess} then
         Guess
      else
         {SqrtIter {Improve Guess}}
      end
   end
in
   {SqrtIter 1.0}
end

% 1.2.1 Procedures and the Processes They Generate - Linear Recursion and Iteration

% Recursive
fun {Factorial N}
   if N == 1 then
      1
   else
      N * {Factorial N-1}
   end
end

{Browse {Factorial 6}}

% Iterative
fun {FactIter Product Counter MaxCount}
   if Counter > MaxCount then
      Product
   else
      {FactIter Counter*Product Counter+1 MaxCount}
   end
end

fun {Factorial_1 N}
   {FactIter 1 1 N}
end

% Iterative, block-structured (from footnote)
fun {Factorial_2 N}
   fun {Iter Product Counter}
      if Counter > N then
         Product
      else
         {Iter Counter*Product Counter+1}
      end
   end
in
   {Iter 1 1}
end

% Exercise 1.9
fun {Inc A} A + 1 end
fun {Dec A} A - 1 end
fun {Plus A B}
   if A == 0 then
      B
   else
      {Inc {Plus {Dec A} B}}
   end
end
fun {Plus_1 A B}
   if A == 0 then
      B
   else
      {Plus_1 {Dec A} {Inc B}}
   end
end

% Exercise 1.10
fun {Ax X Y}
   case X#Y
   of X#0 then 0
   [] 0#Y then 2 * Y
   [] X#1 then 2
   [] X#Y then {Ax X-1 {Ax X Y-1}}
   end
end

{Browse {Ax 1 10}}
{Browse {Ax 2 4}}
{Browse {Ax 3 3}}
fun {Fx N} {Ax 0 N} end
fun {G N} {Ax 1 N} end
fun {H N} {Ax 2 N} end
fun {K N} 5 * N * N end

% 1.2.2 Procedures and the Processes They Generate - Tree Recursion

% Recursive
fun {Fib N}
   case N
   of 0 then 0
   [] 1 then 1
   else {Fib N-1} + {Fib N-2}
   end
end

% Iterative
fun {FibIter A B Count}
   if Count == 0 then
      B
   else
      {FibIter A+B A Count-1}
   end
end
fun {Fib_1 N}
   {FibIter 1 0 N}
end

% Counting change
fun {FirstDenomination KindsOfCoins}
   case KindsOfCoins
   of 1 then 1
   [] 2 then 5
   [] 3 then 10
   [] 4 then 25
   [] 5 then 50
   end
end

fun {CC Amount KindsOfCoins}
   if Amount == 0 then
      1
   elseif Amount < 0 then
      0
   elseif KindsOfCoins == 0 then
      0
   else
      {CC Amount KindsOfCoins-1} +
      {CC Amount-{FirstDenomination KindsOfCoins} KindsOfCoins}
   end
end

fun {CountChange Amount}
   {CC Amount 5}
end

{Browse {CountChange 100}}

% Exercise 1.11
fun {Fy N}
   if N < 3 then
      N
   else
      {Fy N-1} + 2*{Fy N-2} + 3*{Fy N-3}
   end
end

fun {FIter A B C Count}
   if Count == 0 then
      C
   else
      {FIter (A + 2*B + 3*C) A B Count-1}
   end
end

fun {Fz N}
  {FIter 2 1 0 N}
end

% Exercise 1.12
fun {PascalsTriangle Row Col}
   if Row == 0 then
      1
   elseif Col == 0 then
      1
   elseif Row == Col then
      1
   else
      {PascalsTriangle Row-1 Col-1} + {PascalsTriangle Row-1 Col}
   end
end

% 1.2.3 Procedures and the Processes They Generate - Orders of Growth

% Exercise 1.15
fun {Cube X} X * X * X end
fun {Px X} 3.0*X - 4.0*{Cube X} end
fun {Sine Angle}
   if {Not {Abs Angle} > 0.1} then
      Angle
   else
      {Px {Sine Angle/3.0}}
   end
end

% 1.2.4 Procedures and the Processes They Generate - Exponentiation

% Linear recursion
fun {Expt B N}
   if N == 0 then
      1
   else
      B * {Expt B N-1}
   end
end

% Linear iteration
fun {ExptIter B Counter Product}
   if Counter == 0 then
      Product
   else
      {ExptIter B Counter-1 B*Product}
   end
end
fun {Expt_1 B N}
   {ExptIter B N 1}
end

% Logarithmic iteration
fun {Even N} N mod 2 == 0 end

fun {FastExpt B N}
   if N == 0 then
      1
   elseif {Even N} then
      {Square {FastExpt B (N div 2)}}
   else
      B * {FastExpt B N-1}
   end
end

% Exercise 1.16
fun {FastExpIter B N}
   fun {Exp B N A}
      if N == 0 then
         A
      elseif {Even N} then
         {Exp {Square B} (N div 2) A}
      else
         {Exp B N-1 B*A}
      end
   end
in
   {Exp B N 1}
end

% Exercise 1.17
fun {Multiply A B}
   if B == 0 then
      0
   else
      {Plus A {Multiply A B-1}}
   end
end

fun {Halve X} X div 2 end
fun {FastMultiply A B}
   if B == 0 then
      0
   elseif {Even B} then
      {Double {FastMultiply A {Halve B}}}
   else
      {Plus A {Multiply A B-1}}
   end
end

% Exercise 1.18
fun {PeasantMultiply A B}
   fun {Iter A B Accumulator}
      if B == 0 then
         Accumulator
      elseif {Even B} then
         {Iter {Double A} {Halve B} Accumulator}
      else
         {Iter A B-1 Accumulator+A}
      end
   end
in
   {Iter A B 0}
end

% Exercise 1.19
fun {FibIter_ A B P Q Count}
   if Count == 0 then
      B
   elseif {Even Count} then
      {FibIter_ A B (P*P + Q*Q) (2*P*Q + Q*Q) (Count div 2)}
   else
      {FibIter_ (B*Q + A*Q + A*P) (B*P + A*Q) P Q Count-1}
   end
end
fun {Fib_ N}
   {FibIter_ 1 0 0 1 N}
end

% 1.2.5 Procedures and the Processes They Generate - Greatest Common Divisors
fun {Gcd A B}
   if B == 0 then
      A
   else
      {Gcd B (A mod B)}
   end
end

{Browse {Gcd 40 6}}

% Exercise 1.20
fun lazy {NormalOrderMod A B} A mod B end
fun lazy {NormalOrderGcd A B}
   if B == 0 then
      A
   else
      {NormalOrderGcd B {NormalOrderMod A B}}
   end
end
fun {Force A} {Wait A} A end
{Browse {Gcd 206 40}}
{Browse {Force {NormalOrderGcd 206 40}}}

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

% prime
fun {Divides A B} B mod A == 0 end

fun {FindDivisor N TestDivisor}
   if {Square TestDivisor} > N then
      N
   elseif {Divides TestDivisor N} then
      TestDivisor
   else
      {FindDivisor N TestDivisor+1}
   end
end

fun {SmallestDivisor N} {FindDivisor N 2} end

fun {Prime N} N == {SmallestDivisor N} end

% fast_prime
fun {ExpMod NBase NExp M}
   if NExp == 0 then
      1
   elseif {Even NExp} then
      {Square {ExpMod NBase (NExp div 2) M}} mod M
   else
      NBase * {ExpMod NBase NExp-1 M} mod M
   end
end

{OS.srand 0}

fun {RandomInt Min Max}
   X = {OS.rand}
   MinOS
   MaxOS
in
   {OS.randLimits ?MinOS ?MaxOS}
   Min + X*(Max - Min) div (MaxOS - MinOS)
end

fun {FermatTest N}
   fun {TryIt A} {ExpMod A N N} == A end
   Z = {RandomInt 0 N-1}
in
   {TryIt 1+Z}
end

fun {FastPrime N NTimes}
   if NTimes == 0 then
      true
   elseif {FermatTest N} then
      {FastPrime N NTimes-1}
   else
      false
   end
end

% Exercise 1.21
{Browse {SmallestDivisor 199}}
{Browse {SmallestDivisor 1999}}
{Browse {SmallestDivisor 19999}}

% Exercise 1.22
proc {ReportPrime N ElapsedTime}
   {Browse ' *** '#N#ElapsedTime}
end

fun {StartPrimeTest N StartTime}
   if {Prime N} then
      {ReportPrime N {Property.get 'time.user'}-StartTime}
      true
   else
      false
   end
end

fun {TimedPrimeTest N}
   {StartPrimeTest N {Property.get 'time.user'}}
end

proc {SearchForPrimes N I}
   if N > 2 andthen {Even N} then
      {SearchForPrimes N+1 I}
   elseif {TimedPrimeTest N} then
      if I > 1 then
         {SearchForPrimes N+2 I-1}
      end
   else
      {SearchForPrimes N+2 I}
   end
end

{SearchForPrimes 1000 3}
{SearchForPrimes 10000 3}
{SearchForPrimes 100000 3}
{SearchForPrimes 1000000 3}

% Exercise 1.23
fun {NextDivisor N}
   if N == 2 then
      3
   else
      N+2
   end
end
fun {FindDivisor_1 N TestDivisor}
   if {Square TestDivisor} > N then
      N
   elseif {Divides TestDivisor N} then
      TestDivisor
   else
      {FindDivisor_1 N {NextDivisor TestDivisor}}
   end
end

% Exercise 1.24
fun {FastStartPrimeTest N StartTime}
   if {FastPrime N 100} then
      {ReportPrime N {Property.get 'time.user'}-StartTime}
      true
   else
      false
   end
end

fun {FastTimedPrimeTest N}
   {FastStartPrimeTest N {Property.get 'time.user'}}
end

proc {FastSearchForPrimes N I}
   if N > 2 andthen {Even N} then
      {FastSearchForPrimes N+1 I}
   elseif {FastTimedPrimeTest N} then
      if I > 1 then
         {FastSearchForPrimes N+2 I-1}
      end
   else
      {FastSearchForPrimes N+2 I}
   end
end

{FastSearchForPrimes 1000 3}
{FastSearchForPrimes 10000 3}
{FastSearchForPrimes 100000 3}
{FastSearchForPrimes 1000000 3}

% Exercise 1.25
fun {ExpMod_1 NBase NExp M}
   {FastExpt NBase NExp} mod M
end

% Exercise 1.26
fun {ExpMod_2 NBase NExp M}
   if NExp == 0 then
      1
   elseif {Even NExp} then
      {ExpMod_2 NBase (NExp div 2) M} * {ExpMod_2 NBase (NExp div 2) M} mod M
   else
      NBase * {ExpMod_2 NBase NExp-1 M} mod M
   end
end

% Exercise 1.27
fun {Carmichael N}
   {FastPrime N 100} andthen {Not {Prime N}}
end

{Browse {Carmichael 1105}}
{Browse {Carmichael 1729}}
{Browse {Carmichael 2465}}
{Browse {Carmichael 2821}}
{Browse {Carmichael 6601}}

% Exercise 1.28
fun {ExpMod_3 NBase NExp M}
   if NExp == 0 then
      1
   elseif {Even NExp} then
      local
         Candidate = {ExpMod_3 NBase (NExp div 2) M}
         Root = {Square Candidate} mod M
      in
         if Candidate \= 1 andthen Candidate \= M-1 andthen Root == 1 then
            0
         else
            Root
         end
      end
   else
      NBase * {ExpMod_3 NBase NExp-1 M} mod M
   end
end

fun {MillerRabinTest N}
   fun {MillerRabinIteration A T N}
      fun {TryIt A}
         {ExpMod_3 A N-1 N} == 1
      end
   in
      if A == N then
         T > N div 2
      else
         if {TryIt A} then
            {MillerRabinIteration A+1 T+1 N}
         else
            {MillerRabinIteration A+1 T N}
         end
      end
   end
in
   {MillerRabinIteration 1 0 N}
end

{Browse {MillerRabinTest 5}}
{Browse {MillerRabinTest 15}}
{Browse {MillerRabinTest 97}}
{Browse {MillerRabinTest 121}}
{Browse {MillerRabinTest 1003}}
{Browse {MillerRabinTest 1009}}
{Browse {MillerRabinTest 100003}}
{Browse {MillerRabinTest 100005}}
{Browse {MillerRabinTest 561}}
{Browse {MillerRabinTest 1105}}
{Browse {MillerRabinTest 1729}}
{Browse {MillerRabinTest 2465}}
{Browse {MillerRabinTest 2821}}
{Browse {MillerRabinTest 6601}}

% 1.3 Formulating Abstractions with Higher-Order Procedures
fun {Cube_1 X} X * X * X end

% 1.3.1 Formulating Abstractions with Higher-Order Procedures - Procedures as Arguments
fun {SumIntegers A B}
   if A > B then
      0
   else
      A + {SumIntegers A+1 B}
   end
end

fun {SumCubes A B}
   if A > B then
      0
   else
      {Cube A} + {SumCubes A+1 B}
   end
end

fun {PiSum A B}
   if A > B then
      0.0
   else
      1.0/(A * (A + 2.0)) + {PiSum A+4.0 B}
   end
end

fun {Sum Term A Next B}
   if A > B then
      0
   else
      {Term A} + {Sum Term {Next A} Next B}
   end
end

% Using sum
fun {Inc_1 N} N + 1 end

fun {SumCubes_1 A B}
   {Sum Cube_1 A Inc B}
end

{Browse {SumCubes_1 1 10}}

fun {Identity X} X end

fun {SumIntegers_1 A B}
   {Sum Identity A Inc_1 B}
end

{Browse {SumIntegers_1 1 10}}

fun {SumReal Term A Next B}
   if A > B then
      0.0
   else
      {Term A} + {SumReal Term {Next A} Next B}
   end
end

fun {PiSum_1 A B}
   fun {PiTerm X} 1.0 / (X * (X + 2.0)) end
   fun {PiNext X} X + 4.0 end
in
   {SumReal PiTerm A PiNext B}
end

{Browse 8.0 * {PiSum_1 1.0 1000.0}}

fun {Integral F A B Dx}
   fun {AddDx X} X + Dx end
in
   {SumReal F A+(Dx / 2.0) AddDx B} * Dx
end

fun {CubeReal X} X * X * X end

{Browse {Integral CubeReal 0.0 1.0 0.01}}
{Browse {Integral CubeReal 0.0 1.0 0.001}}

% Exercise 1.29
fun {Simpson F A B N}
   H = {Abs B-A} / {IntToFloat N}
   fun {SumIter Term Start Next Stop Acc}
      if Start > Stop then
         Acc
      else
         {SumIter Term {Next Start} Next Stop (Acc + {Term A + {IntToFloat Start}*H})}

      end
   end
in
   H * {SumIter F 1 Inc N 0.0}
end
{Browse {Simpson CubeReal 0.0 1.0 100}}

% Exercise 1.30
fun {Sum_1 Term A Next B}
   fun {Iter A Result}
      if A > B then
         Result
      else
         {Iter {Next A} (Result + {Term A})}
      end
   end
in
   {Iter A 0}
end
fun {SumCubes_2 A B}
   {Sum_1 Cube A Inc B}
end
{Browse {SumCubes_2 1 10}}

% Exercise 1.31
fun {Product Term A Next B}
   if A > B then
      1
   else
      {Term A} * {Product Term {Next A} Next B}
   end
end
fun {Factorial_3 N}
   {Product Identity 1 Inc N}
end
{Browse {Factorial_3 5}}

fun {ProductIter Term A Next B Acc}
   if A > B then
      Acc
   else
      {ProductIter Term {Next A} Next B (Acc * {Term A})}
   end
end

fun {WallisPi N}
   fun {WallisTerm K}
      Nom = K + if {Even K} then 2 else 1 end
      Denom = K + if {Even K} then 1 else 2 end
   in
      {IntToFloat Nom} / {IntToFloat Denom}
   end
in
   4.0 * {ProductIter WallisTerm 1 Inc N 1.0}
end
{Browse {WallisPi 100}}

% Exercise 1.32
fun {Accumulate Combiner NullValue Term A Next B}
   if A > B then
      NullValue
   else
      {Combiner {Term A} {Accumulate Combiner NullValue Term {Next A} Next B}}
   end
end
fun {Sum_2     A B} {Accumulate Number.'+' 0 Identity A Inc B} end
fun {Product_2 A B} {Accumulate Number.'*' 1 Identity A Inc B} end

fun {AccumulateIter Combiner Term A Next B Acc}
   if A > B then
      Acc
   else
      {AccumulateIter Combiner Term {Next A} Next B {Combiner Acc {Term A}}}
   end
end
fun {Sum_3     A B} {AccumulateIter Number.'+' Identity A Inc B 0} end
fun {Product_3 A B} {AccumulateIter Number.'*' Identity A Inc B 1} end

% Exercise 1.33
fun {FilteredAccumulate Combiner NullValue Term A Next B Pred}
   if A > B then
      NullValue
   elseif {Pred A} then
      {Combiner {Term A} {FilteredAccumulate Combiner NullValue Term {Next A} Next B Pred}}
   else
      {FilteredAccumulate Combiner NullValue Term {Next A} Next B Pred}
   end
end

fun {SumSquaresOfPrimes A B}
   {FilteredAccumulate Number.'+' 0 Square A Inc B Prime}
end
{Browse {SumSquaresOfPrimes 2 5}}

fun {ProductOfRelativelyPrime N}
   fun {IsRelativelyPrimeToN K}
      {Gcd K N} == 1
   end
in
   {FilteredAccumulate Number.'*' 1 Identity 1 Inc N-1 IsRelativelyPrimeToN}
end

% 1.3.2 Formulating Abstractions with Higher-Order Procedures - Constructing Procedures Using Lambda
fun {PiSum_2 A B}
  {SumReal fun {$ X} 1.0 / (X * (X + 2.0)) end A fun {$ X} X + 4.0 end B}
end

fun {Integral_1 F A B Dx}
   {SumReal F A+(Dx / 2.0) fun {$ X} X + Dx end B} * Dx
end

fun {Plus4 X} X + 4 end

Plus4_1 = fun {$ X} X + 4 end

{Browse {fun {$ X Y Z} X + Y + {Square Z} end 1 2 3}}

% Using let
fun {F_1 X Y}
   fun {FHelper A B}
      X*{Square A} + Y*B + A*B
   end
in
   {FHelper (1 + X*Y) 1-Y}
end

fun {F_2 X Y}
   {fun {$ A B} X*{Square A} + Y*B + A*B end
      (1 + X*Y) 1-Y}
end

fun {F_3 X Y}
   A = 1 + X*Y
   B = 1 - Y
in
   X*{Square A} + Y*B + A*B
end

Xa = 5
{Browse
   local
      Xa = 3
   in
      Xa + Xa*10
   end + Xa}

Xb = 2
{Browse
   local
      Xb = 3
      Y = Xb + 2
   in
      Xb * Y
   end}

fun {F_4 X Y}
   A = 1 + X*Y
   B = 1 - Y
in
   X*{Square A} + Y*B + A*B
end

% Exercise 1.34
fun {F_5 G} {G 2} end
{Browse {F_5 Square}}
{Browse {F_5 fun {$ Z} Z * (Z + 1) end}}
% {Browse {F_5 F_5}}

% 1.3.3 Formulating Abstractions with Higher-Order Procedures - Procedures as General Methods

% Half-interval method
fun {CloseEnough X Y}
   {Abs X-Y} < 0.001
end

fun {Positive X} X >= 0.0 end
fun {Negative X} {Not {Positive X}} end

fun {Searchx F NegPoint PosPoint}
   MidPoint = {Average NegPoint PosPoint}
in
   if {CloseEnough NegPoint PosPoint} then
      MidPoint
   else
      local
         TestValue = {F MidPoint}
      in
         if {Positive TestValue} then
            {Searchx F NegPoint MidPoint}
         elseif {Negative TestValue} then
            {Searchx F MidPoint PosPoint}
         else
            MidPoint
         end
      end
   end
end

fun {HalfIntervalMethod F A B}
   AValue = {F A}
   BValue = {F B}
in
   if {Negative AValue} andthen {Positive BValue} then
      {Searchx F A B}
   elseif {Negative BValue} andthen {Positive AValue} then
      {Searchx F B A}
   else
      raise invalid('Values are not of opposite sign ' # A # ' ' # B) end
   end
end

{Browse {HalfIntervalMethod Sin 2.0 4.0}}

{Browse {HalfIntervalMethod fun {$ X} X*X*X - 2.0*X - 3.0 end 1.0 2.0}}

% Fixed points
Tolerance = 0.00001

fun {FixedPoint F FirstGuess}
   fun {CloseEnough V1 V2}
      {Abs V1-V2} < Tolerance
   end
   fun {Try Guess}
      Next = {F Guess}
   in
      if {CloseEnough Guess Next} then
         Next
      else
         {Try Next}
      end
   end
in
   {Try FirstGuess}
end

{Browse {FixedPoint Cos 1.0}}

{Browse {FixedPoint fun {$ Y} {Sin Y} + {Cos Y} end 1.0}}

% note: this function does not converge
fun {Sqrt_4 X}
   {FixedPoint fun {$ Y} X / Y end 1.0}
end

fun {Sqrt_5 X}
   {FixedPoint fun {$ Y} {Average Y X/Y} end 1.0}
end

% Exercise 1.35
fun {GoldenRatio}
  {FixedPoint fun {$ X} 1.0 + 1.0/X end 1.0}
end
{Browse {GoldenRatio}}

% Exercise 1.36
% 35 guesses before convergence
{Browse {FixedPoint fun {$ X} {Log 1000.0} / {Log X} end 1.5}}
% 11 guesses before convergence (AverageDamp defined below)
%{Browse {FixedPoint {AverageDamp fun {$ X} {Log 1000.0} / {Log X} end} 1.5}}

% Exercise 1.37
fun {ContFrac N D K}
   fun {Frac I}
      {N I} / ({D I} + if I == K then 0.0 else {Frac I+1} end)
   end
in
   {Frac 1}
end
{Browse {ContFrac fun {$ I} 1.0 end fun {$ I} 1.0 end 11}}

fun {ContFracIter N D K}
   fun {FracIter I Result}
      if I == 0 then
         Result
      else
         {FracIter I-1 {N I}/({D I} + Result)}
      end
   end
in
   {FracIter K 0.0}
end
{Browse {ContFracIter fun {$ I} 1.0 end fun {$ I} 1.0 end 11}}

% Exercise 1.38
{Browse
   {ContFrac
      fun {$ I} 1.0 end
      fun {$ I}
         if (I+1) mod 3 == 0 then
            2.0 * ({IntToFloat I}+1.0)/3.0
         else
            1.0
         end
      end
      10}}

% Exercise 1.39
fun {TanCF X K}
   fun {N I}
      if I == 1 then
         X
      else
         ~(X*X)
      end
   end
   fun {D I}
      {IntToFloat I}*2.0 - 1.0
   end
in
   {ContFrac N D K}
end
fun {DegreesToRadians D}
   (D/360.0) * 2.0 * 3.14
end
{Browse {TanCF {DegreesToRadians 30.0} 1000}}

% 1.3.4 Formulating Abstractions with Higher-Order Procedures - Procedures as Returned Values
fun {AverageDamp F}
   fun {$ X} {Average X {F X}} end
end

{Browse {{AverageDamp Square} 10.0}}

fun {Sqrt_6 X}
   {FixedPoint {AverageDamp fun {$ Y} X / Y end} 1.0}
end

fun {CubeRoot X}
   {FixedPoint {AverageDamp fun {$ Y} X / {Square Y} end} 1.0}
end

% Newton's method
Dx = 0.00001
fun {Deriv G}
   fun {$ X} ({G X+Dx} - {G X}) / Dx end
end

fun {Cube_2 X} X * X * X end

{Browse {{Deriv Cube_2} 5.0}}

fun {NewtonTransform G}
   fun {$ X} X - {G X} / {{Deriv G} X} end
end

fun {NewtonsMethod G Guess}
   {FixedPoint {NewtonTransform G} Guess}
end

fun {Sqrt_7 X}
   {NewtonsMethod fun {$ Y} {Square Y} - X end 1.0}
end

% Fixed point of transformed function
fun {FixedPointOfTransform G Transform Guess}
   {FixedPoint {Transform G} Guess}
end

fun {Sqrt_8 X}
   {FixedPointOfTransform fun {$ Y} X / Y end AverageDamp 1.0}
end

fun {Sqrt_9 X}
   {FixedPointOfTransform fun {$ Y} {Square Y} - X end NewtonTransform 1.0}
end

% Exercise 1.40
fun {Cubic A B C}
   fun {$ X} {Cube X} + A*X*X + B*X + C end
end
{Browse {NewtonsMethod {Cubic 5.0 3.0 2.5} 1.0}}

% Exercise 1.41
fun {Double_ F}
   fun {$ X} {F {F X}} end
end
{Browse {{Double_ Inc} 5}}
{Browse {{{Double_ Double_} Inc} 5}}
{Browse {{{Double_ {Double_ Double_}} Inc} 5}}

% Exercise 1.42
fun {Compose F G}
   fun {$ X} {F {G X}} end
end
{Browse {{Compose Square Inc} 6}}

% Exercise 1.43
fun {Repeated F N}
   if N == 0 then
      Identity
   else
      {Compose F {Repeated F N-1}}
   end
end
{Browse {{Repeated Square 2} 5}}

% Exercise 1.44
fun {Smooth F}
   Dx = 0.00001
in
   fun {$ X} ({F X-Dx} + {F X} + {F X+Dx}) / 3.0 end
end
{Browse {FixedPoint {Smooth fun {$ X} {Log 1000.0} / {Log X} end} 1.5}}
fun {NFoldSmooth F N}
   {Repeated {Smooth F} N}
end

% Exercise 1.45
fun {RepeatedDampenRoot X NRoot NRepeat}
  {FixedPointOfTransform
      fun {$ Y} {Average Y X/{Pow Y {IntToFloat NRoot-1}}} end
      {Repeated AverageDamp NRepeat}
      1.0}
end
{Browse {RepeatedDampenRoot 625.0 4 2}}

% Exercise 1.46
fun {IterativeImprove GoodEnough Improve}
   fun {Iterate Guess}
      Next = {Improve Guess}
   in
      if {GoodEnough Guess Next} then
         Next
      else
         {Iterate Next}
      end
   end
in
   fun {$ X} {Iterate X} end
end

fun {Sqrt_10 X}
   ToleranceX = 0.00001
in
   {
      {IterativeImprove
         fun {$ G N}
            {Abs N*N - X} < ToleranceX
         end
         fun {$ G}
            (G + X/G) / 2.0
         end}
      1.0
   }
end
{Browse {Sqrt_10 25.0}}

fun {FixedPoint_ F FirstGuess}
   ToleranceX = 0.00001
   fun {GoodEnough V1 V2}
      {Abs V1-V2} < ToleranceX
   end
in
   {{IterativeImprove GoodEnough F} FirstGuess}
end
{Browse {FixedPoint_ {AverageDamp fun {$ X} {Log 1000.0} / {Log X} end} 1.5}}

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