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 #02 Examples in Oz
% Functions defined in previous chapters
fun {Gcd A B}
   if B == 0 then
      A
   else
      {Gcd B (A mod B)}
   end
end

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

fun {Identity X} X end

fun {Square X} X * X end

% 2 Building Abstractions with Data
fun {LinearCombination A B X Y}
   A*X + B*Y
end

fun {Mul A B}
   A * B
end
fun {LinearCombination1 A B X Y}
   {Mul A X} + {Mul B Y}
end

% 2.1.1 Introduction to Data Abstraction - Example: Arithmetic Operations for Rational Numbers

fun {MakeRat N D} N#D end
fun {Numer X} X.1 end
fun {Denom X} X.2 end

fun {AddRat X Y}
   {MakeRat
      {Numer X}*{Denom Y} + {Numer Y}*{Denom X}
      {Denom X}*{Denom Y}}
end

fun {SubRat X Y}
   {MakeRat
      {Numer X}*{Denom Y} - {Numer Y}*{Denom X}
      {Denom X}*{Denom Y}}
end

fun {MulRat X Y}
   {MakeRat
      {Numer X}*{Numer Y}
      {Denom X}*{Denom Y}}
end

fun {DivRat X Y}
   {MakeRat
      {Numer X}*{Denom Y}
      {Denom X}*{Numer Y}}
end

fun {EqualRat X Y}
   {Numer X}*{Denom Y} == {Numer Y}*{Denom X}
end

fun {CONS X Y} X|Y end
fun {CAR L} L.1 end
fun {CDR L} L.2 end

% Compose function courtesy of Kevin Glyn via Oz mailing list
fun {Compose F G}
   fun {$ X}
      {F {G X}}
   end
end
CADR = {Compose CAR CDR}

X = {CONS 1 2}
Y = {CADR 1|2|3|4}
{Browse Y}

{Browse {CAR X}}
{Browse {CDR X}}

X1 = {CONS 1 2}
Y1 = {CONS 3 4}
Z1 = {CONS X1 Y1}
{Browse {CAR {CAR Z1}}}
{Browse {CAR {CDR Z1}}}

% footnote -- alternative definitions
MakeRat1 = CONS
Numer1 = CAR
Denom1 = {Compose CAR CDR}

proc {PrintRat X}
   {Browse {StringToAtom {Append {IntToString {Numer X}} {Append "/" {IntToString {Denom X}}}}}}
end

OneHalf = {MakeRat 1 2}
{PrintRat OneHalf}

OneThird = {MakeRat 1 3}
{PrintRat {AddRat OneHalf OneThird}}
{PrintRat {MulRat OneHalf OneThird}}
{PrintRat {AddRat OneThird OneThird}}

% reducing to lowest terms in constructor
fun {MakeRatGcd N D}
   G = {Gcd N D}
in
   (N div G)#(D div G)
end

fun {AddRatGcd X Y}
   {MakeRatGcd
      {Numer X}*{Denom Y} + {Numer Y}*{Denom X}
      {Denom X}*{Denom Y}}
end

{PrintRat {AddRatGcd OneThird OneThird}}

% Exercise 2.1
fun {MakeRat_ N D}
   if (D < 0 andthen N < 0) orelse N < 0 then
      (D * ~1)#(N * ~1)
   else
      D#N
   end
end

% Module Translation
   RATIONAL =
      functor
      export
         numericType : NumericType
         make        : Make
         numer       : Numer
         denom       : Denom
         add         : Add
         subtract    : Sub
         multiply    : Mul
         divide      : Div
         equal       : Equal
         toString    : ToString
      define
         NumericType = rational
         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 {Numer rational(N D)} N end
         fun {Denom rational(N D)} D end
         fun {Add X Y} {Make {Numer X}*{Denom Y} + {Numer Y}*{Denom X} {Denom X}*{Denom Y}} end
         fun {Sub X Y} {Make {Numer X}*{Denom Y} - {Numer Y}*{Denom X} {Denom X}*{Denom Y}} end
         fun {Mul X Y} {Make {Numer X}*{Numer Y} {Denom X}*{Denom Y}} end
         fun {Div X Y} {Make {Numer X}*{Denom Y} {Denom X}*{Numer Y}} end
         fun {Equal X Y} {Numer X}*{Denom Y} == {Numer Y}*{Denom X} end
         fun {ToString X}
            {StringToAtom {Append {IntToString {Numer X}} {Append "/" {IntToString {Denom X}}}}}
         end
      end
   [Rational] = {Module.apply [RATIONAL]}

   local
      OneHalf = {Rational.make 1 2}
      OneThird = {Rational.make 1 3}
   in
      {Browse {Rational.toString OneHalf}}
      {Browse {Rational.toString {Rational.add OneHalf OneThird}}}
      {Browse {Rational.toString {Rational.multiply OneHalf OneThird}}}
      {Browse {Rational.toString {Rational.add OneThird OneThird}}}
   end
% end Module Translation

% Object Translation
   class RationalOO
      feat Numer Denom
      meth init(N D)
         G = {Abs {Gcd N D}}
      in
         self.Numer = if D >= 0 then N else ~N end div G
         self.Denom = {Abs D} div G
      end
      meth add(Other ?$)
         {New RationalOO init(self.Numer*Other.Denom + Other.Numer*self.Denom self.Denom*Other.Denom)}
      end
      meth subtract(Other ?$)
         {New RationalOO init(self.Numer*Other.Denom - Other.Numer*self.Denom self.Denom*Other.Denom)}
      end
      meth multiply(Other ?$)
         {New RationalOO init(self.Numer*Other.Numer self.Denom*Other.Denom)}
      end
      meth divide(Other ?$)
         {New RationalOO init(self.Numer*Other.Denom self.Denom*Other.Numer)}
      end
      meth equal(Other ?$)
         self.Numer * Other.Denom == Other.Numer * self.Denom
      end
      meth toString(?$)
         {StringToAtom {Append {IntToString self.Numer} {Append "/" {IntToString self.Denom}}}}
      end
   end

   local
      OneHalf = {New RationalOO init(1 2)}
      OneThird = {New RationalOO init(1 3)}
   in
      {Browse {OneHalf toString($)}}
      {Browse {{OneHalf add(OneThird $)} toString($)}}
      {Browse {{OneHalf multiply(OneThird $)} toString($)}}
      {Browse {{OneThird add(OneThird $)} toString($)}}
   end
% end Object Translation

% 2.1.2 Introduction to Data Abstraction - Abstraction barriers

% reducing to lowest terms in selectors
fun {MakeRat2 N D} N#D end

fun {Numer2 N#D}
   G = {Gcd N D}
in
   N div G
end

fun {Denom2 N#D}
   G = {Gcd N D}
in
   D div G
end

% Exercise 2.2
fun {MakePoint X Y} X#Y end
fun {XPoint Point} Point.1 end
fun {YPoint Point} Point.2 end
fun {MakeSegment StartSegment EndSegment} StartSegment#EndSegment end
fun {StartSegment Segment} Segment.1 end
fun {EndSegment Segment} Segment.2 end
fun {MidpointSegment Segment}
   S = {StartSegment Segment}
   E = {EndSegment Segment}
in
   {MakePoint (({XPoint S} + {XPoint E}) / 2.0) (({YPoint S} + {YPoint E}) / 2.0)}
end
proc {PrintPoint P}
   {Browse {StringToAtom {Append "(" {Append {FloatToString {XPoint P}} {Append "," {Append {FloatToString {YPoint P}} ")"}}}}}}
end
{PrintPoint {MidpointSegment {MakeSegment {MakePoint 4.0 6.0} {MakePoint 9.0 15.0}}}}

% Exercise 2.3
fun {RectPerimeter Rect}
   2.0*{RectWidth Rect} + 2.0*{RectHeight Rect}
end
fun {RectArea Rect}
   {RectWidth Rect} * {RectHeight Rect}
end

% Representation 1: stores the two opposing points P1 and P2
fun {PtsMakeRectangle P1 P2} pts(P1 P2) end
fun {PtsRectWidth pts(P1 P2)} {Abs {XPoint P1} - {XPoint P2}} end
fun {PtsRectHeight pts(P1 P2)} {Abs {YPoint P1} - {YPoint P2}} end

% Representation 2: stores the achor point and width/height
fun {PwhMakeRectangle P Width Height} pwh(P Width Height) end
fun {PwhRectWidth pwh(P Width Height)} Width end
fun {PwhRectHeight pwh(P Width Height)} Height end

fun {RectWidth Rect}
   case Rect
   of pts(...) then {PtsRectWidth Rect}
   [] pwh(...) then {PwhRectWidth Rect}
   end
end
fun {RectHeight Rect}
   case Rect
   of pts(...) then {PtsRectHeight Rect}
   [] pwh(...) then {PwhRectHeight Rect}
   end
end

Rx = {PtsMakeRectangle {MakePoint 10.0 15.0} {MakePoint 30.0 40.0}}
Ry = {PwhMakeRectangle {MakePoint 10.0 15.0} 20.0 25.0}

{Browse {RectPerimeter Rx}#{RectArea Rx}}
{Browse {RectPerimeter Ry}#{RectArea Ry}}

% 2.1.3 Introduction to Data Abstraction - What is meant by data?
fun {CONS1 X Y}
   fun {$ N}
      case N
      of 0 then X
      [] 1 then Y
      else raise illFormedExpression('Argument not 0 or 1 -- CONS ' # m) end
      end
   end
end
fun {CAR1 Z} {Z 0} end
fun {CDR1 Z} {Z 1} end

% Exercise 2.4
fun {CONS2 X Y}
   fun {$ M}
      {M X Y}
   end
end
fun {CAR2 Z}
   {Z fun {$ P Q} P end}
end
fun {CDR2 Z}
   {Z fun {$ P Q} Q end}
end

% Exercise 2.5
fun {CountPowers N D}
   fun {Iter I Pow}
      if I mod D == 0 then
         {Iter (I div D) Pow+1}
      else
         Pow
      end
   end
in
   {Iter N 0}
end
fun {CONS3 X Y}
   {Pow 2 X} * {Pow 3 Y}
end
fun {CAR3 Z}
   {CountPowers Z 2}
end
fun {CDR3 Z}
   {CountPowers Z 3}
end

{Browse {CONS3 1 2}}
{Browse {CAR3 {CONS3 1 2}}}
{Browse {CDR3 {CONS3 1 2}}}

% Exercise 2.6
Zero = fun {$ F} fun {$ X} X end end
fun {Add1 N}
   fun {$ F}
      fun {$ X}
         {F {{N F} X}}
      end
   end
end

% 2.1.4 Introduction to Data Abstraction - Extended Exercise: Interval Arithmetic
fun {AddInterval X Y}
   {MakeInterval {LowerBound X}+{LowerBound Y} {UpperBound X}+{UpperBound Y}}
end

fun {MulInterval X Y}
   P1 = {LowerBound X} * {LowerBound Y}
   P2 = {LowerBound X} * {UpperBound Y}
   P3 = {UpperBound X} * {LowerBound Y}
   P4 = {UpperBound X} * {UpperBound Y}
in
   {MakeInterval
      {Min {Min P1 P2} {Min P3 P4}}
      {Max {Max P1 P2} {Max P3 P4}}}
end

fun {DivInterval X Y}
   Z = {MakeInterval 1.0/{UpperBound Y} 1.0/{LowerBound Y}}
in
   {MulInterval X Z}
end

fun {MakeCenterWidth C W}
   {MakeInterval C-W C+W}
end

fun {Center I}
   ({LowerBound I} + {UpperBound I}) / 2.0
end

fun {Width I}
   ({UpperBound I} - {LowerBound I}) / 2.0
end

% Exercise 2.7
fun {MakeInterval A B} A#B end
fun {LowerBound X#Y} X end
fun {UpperBound X#Y} Y end

% Exercise 2.8
fun {SubInterval X Y}
   {MakeInterval {LowerBound X}-{UpperBound Y} {UpperBound X}-{LowerBound Y}}
end

% Exercise 2.9
I = {MakeInterval 5.0 10.0}
J = {MakeInterval 15.0 25.0}

% width of the sum (or difference) of two intervals *is* a function only of the widths of
% the intervals being added (or subtracted)
{Browse {Width {AddInterval I J}}#({Width I} + {Width J})}
{Browse {Width {SubInterval I J}}#({Width I} + {Width J})}

% width of the product (or quotient) of two intervals *is not* a function only of the widths
% of the intervals being multiplied (or divided)
{Browse {Width {MulInterval I J}}#({Width I} + {Width J})}
{Browse {Width {DivInterval I J}}#({Width I} + {Width J})}

% Exercise 2.10
fun {IsZeroInterval I}
   ({LowerBound I} == 0) orelse ({UpperBound I} == 0)
end
fun {DivIntervalZeroCheck X Y}
   if {IsZeroInterval Y} then
      raise error("Zero interval divisor") end
   else
      {DivInterval X Y}
   end
end

% Exercise 2.11
fun {OptMulInterval X Y}
   UpperX = {UpperBound X}
   LowerX = {LowerBound X}
   UpperY = {UpperBound Y}
   LowerY = {LowerBound Y}
in
   case (UpperX >= 0)#(LowerX >= 0)#(UpperY >= 0)#(LowerY >= 0)
      of true #true #true #true  then {MakeInterval LowerX*LowerY UpperX*UpperY}
      [] true #true #true #false then {MakeInterval UpperX*LowerY UpperX*UpperY}
      [] true #true #false#false then {MakeInterval UpperX*LowerY LowerX*UpperY}
      [] true #false#true #true  then {MakeInterval UpperY*LowerX UpperY*UpperX}
      [] true #false#false#false then {MakeInterval UpperX*LowerY LowerX*LowerY}
      [] false#false#true #true  then {MakeInterval LowerX*UpperY LowerY*UpperX}
      [] false#false#true #false then {MakeInterval LowerX*UpperY LowerY*LowerX}
      [] false#false#false#false then {MakeInterval UpperX*UpperY LowerY*LowerX}
      [] true #false#true #false then
         local
            P1 = {LowerBound X} * {LowerBound Y}
            P2 = {LowerBound X} * {UpperBound Y}
            P3 = {UpperBound X} * {LowerBound Y}
            P4 = {UpperBound X} * {UpperBound Y}
         in
            {MakeInterval
               {Min {Min P1 P2} {Min P3 P4}}
               {Max {Max P1 P2} {Max P3 P4}}}
         end
      else raise 'multiply interval exception' end
   end
end

% Exercise 2.12
fun {MakeCenterPercent C P}
   {MakeCenterWidth C {Abs P*C/100.0}}
end
fun {Percent I}
   {Width I} / {Abs {Center I}} * 100.0
end

% Exercise 2.14
% parallel resistors
fun {Par1 R1 R2}
   {DivInterval {MulInterval R1 R2} {AddInterval R1 R2}}
end

fun {Par2 R1 R2}
   One = {MakeInterval 1.0 1.0}
in
   {DivInterval One {AddInterval {DivInterval One R1} {DivInterval One R2}}}
end

R1 = {MakeCenterWidth 5.0 0.1}
R2 = {MakeCenterWidth 10.0 0.1}
{Browse {Par1 R1 R2}}
{Browse {Par2 R1 R2}}

% Module Translation
   INTERVAL =
      functor
      export
         makeInterval    : MakeInterval
         lowerBound      : LowerBound
         upperBound      : UpperBound
         addInterval     : AddInterval
         mulInterval     : MulInterval
         divInterval     : DivInterval
         makeCenterWidth : MakeCenterWidth
         center          : Center
         width           : Width
      define
         fun {MakeInterval A B} A#B end
         fun {LowerBound X#Y} X end
         fun {UpperBound X#Y} Y end
         fun {AddInterval X Y}
            {MakeInterval {LowerBound X}+{LowerBound Y} {UpperBound X}+{UpperBound Y}}
         end
         fun {MulInterval X Y}
            P1 = {LowerBound X} * {LowerBound Y}
            P2 = {LowerBound X} * {UpperBound Y}
            P3 = {UpperBound X} * {LowerBound Y}
            P4 = {UpperBound X} * {UpperBound Y}
         in
            {MakeInterval {Min {Min P1 P2} {Min P3 P4}} {Max {Max P1 P2} {Max P3 P4}}}
         end
         fun {DivInterval X Y}
            Z = {MakeInterval 1.0/{UpperBound Y} 1.0/{LowerBound Y}}
         in
            {MulInterval X Z}
         end
         fun {MakeCenterWidth C W} {MakeInterval C-W C+W} end
         fun {Center I} ({LowerBound I} + {UpperBound I}) / 2.0 end
         fun {Width I} ({UpperBound I} - {LowerBound I}) / 2.0 end
      end

   [Interval] = {Module.apply [INTERVAL]}
% end Module Translation *)

% Object Translation
   class IntervalOO
      feat UpperBound LowerBound
      meth init(X Y)
         self.UpperBound = X
         self.LowerBound = Y
      end
      meth addInterval(Other ?$)
         {New IntervalOO init(self.LowerBound*Other.LowerBound self.UpperBound*Other.UpperBound)}
      end
      meth mulInterval(Other ?$)
         P1 = self.LowerBound * Other.LowerBound
         P2 = self.LowerBound * Other.UpperBound
         P3 = self.UpperBound * Other.LowerBound
         P4 = self.UpperBound * Other.UpperBound
      in
         {New IntervalOO init({Min {Min P1 P2} {Min P3 P4}} {Max {Max P1 P2} {Max P3 P4}})}
      end
      meth divInterval(Other ?$)
         Z = {New IntervalOO init(1.0/Other.UpperBound 1.0/Other.LowerBound)}
      in
         {MulInterval X Z}
      end
      meth makeCenterWidth(C W ?$)
         {New IntervalOO init(C-W C+W)}
      end
      meth center(?$)
         (self.LowerBound + self.UpperBound) / 2.0
      end
      meth width(?$)
         (self.UpperBound - self.LowerBound) / 2.0
      end
   end
% end Object Translation *)

% 2.2.1 Hierarchical Data and the Closure Property - Representing Sequences

{Browse 1|2|3|4|nil}

fun {Head L} L.1 end
fun {Tail L} L.2 end

OneThroughFour = [1 2 3 4]

{Browse OneThroughFour}
{Browse {Head OneThroughFour}}
{Browse {Tail OneThroughFour}}
{Browse {Head {Tail OneThroughFour}}}
{Browse 10|OneThroughFour}
{Browse 5|OneThroughFour}

fun {ListRef Items N}
   case N
   of 0 then {Head Items}
   else {ListRef {Tail Items} N-1}
   end
end

Squares = [1 4 9 16 25]
{Browse {ListRef Squares 3}}

fun {Length1 Items}
   case Items
   of nil then 0
   else 1 + {Length1 {Tail Items}}
   end
end

Odds = [1 3 5 7]
{Browse {Length1 Odds}}

fun {Length2 Items}
   fun {LengthIter L Count}
      case L
      of nil then Count
      else {LengthIter {Tail L} 1+Count}
      end
   end
in
   {LengthIter Items 0}
end

fun {Append1 L1 L2}
   case L1
   of nil then L2
   else {Head L1}|{Append1 {Tail L1} L2}
   end
end

{Browse {Append1 Squares Odds}}
{Browse {Append1 Odds Squares}}

% Mapping over lists
fun {ScaleList Items Factor}
   case Items
   of nil then nil
   else {Head Items} * Factor | {ScaleList {Tail Items} Factor}
   end
end

{Browse {ScaleList [1 2 3 4 5] 10}}

fun {Map1 Items Proc}
   case Items
   of nil then nil
   else
      {Proc {Head Items}} | {Map1 {Tail Items} Proc}
   end
end

{Browse {Map1 [~10.0 2.5 ~11.6 17.0] Abs}}

{Browse {Map1 [1 2 3 4] fun {$ X} X * X end}}

fun {ScaleList2 Items Factor}
   {Map1 Items fun {$ X} X * Factor end}
end

/* Not sure how to translate these to Oz?
   (map + (list 1 2 3) (list 40 50 60) (list 700 800 900))
   (map (lambda (x y) (+ x ( * 2 y))) (list 1 2 3) (list 4 5 6))
*/

% Exercise 2.17
fun {LastPair L}
   case L
   of nil then nil
   [] H|nil then L
   [] H|T then {LastPair T}
   end
end
{Browse {LastPair [23 72 149 34]}}

% Exercise 2.18
fun {Reverse1 L}
   case L
   of nil then nil
   [] H|T then {Append {Reverse1 T} [H]}
   end
end
fun {Reverse2 L}
   fun {ReverseIter L Accum}
      case L
      of nil then Accum
      [] H|T then {ReverseIter T H|Accum}
      end
   end
in
   {ReverseIter L nil}
end
{Browse {Reverse1 [1 4 9 16 25]}}
{Browse {Reverse2 [1 4 9 16 25]}}

% Exercise 2.19
fun {NoMore CoinValues} CoinValues == nil end
fun {ExceptFirstDenomination CoinValues} CoinValues.2 end
fun {FirstDenomination CoinValues} CoinValues.1 end
fun {CC Amount CoinValues}
   if Amount == 0 then
      1
   else
      if Amount < 0 orelse {NoMore CoinValues} then
         0
      else
         {CC Amount {ExceptFirstDenomination CoinValues}} +
         {CC Amount-{FirstDenomination CoinValues} CoinValues}
      end
   end
end
USCoins = [50 25 10 5 1]
{Browse {CC 100 USCoins}}
% Note: Oz doesn't like mixing ints and floats - scale by 2 and convert to int
UKCoins = {Map1 {ScaleList [100.0 50.0 20.0 10.0 5.0 2.0 1.0 0.5] 2.0} FloatToInt}
{Browse {CC 2*100 UKCoins}}

% Exercise 2.20
fun {Filter1 L Pred}
   case L
   of nil then nil
   [] H|T then
      if {Pred H} then
         H|{Filter1 T Pred}
      else
         {Filter1 T Pred}
      end
   end
end
fun {SameParity L}
   Pred = if {IsOdd L.1} then IsOdd else IsEven end
in
   {Filter1 L.2 Pred}
end
{Browse {SameParity [1 2 3 4 5 6 7]}}
{Browse {SameParity [2 3 4 5 6 7]}}

% Exercise 2.21
fun {SquareList1 L}
   case L
   of nil then nil
   [] H|T then (H*H)|{SquareList1 T}
   end
end
fun {SquareList2 L}
   {Map L fun {$ X} X*X end}
end
{Browse {SquareList1 [1 2 3 4]}}
{Browse {SquareList2 [1 2 3 4]}}

% Exercise 2.22
fun {SquareList3 L}
   fun {Iter L Answer}
      case L
      of nil then Answer
      [] H|T then {Iter T (H*H)|Answer}
      end
   end
in
   {Iter L nil}
end
fun {SquareList4 L}
   fun {Iter L Answer}
      case L
      of nil then Answer
      [] H|T then {Iter T {Append Answer [H*H]}}
      end
   end
in
   {Iter L nil}
end
fun {SquareList5 L}
   fun {Iter L Answer}
      case L
      of nil then Answer
      [] H|T then {Iter T (H*H)|Answer}
      end
   end
in
   {Reverse {Iter L nil}}
end
{Browse {SquareList3 [1 2 3 4]}}
{Browse {SquareList4 [1 2 3 4]}}
{Browse {SquareList5 [1 2 3 4]}}

% Exercise 2.23
proc {ForEach L F}
   case L
   of nil then skip
   [] H|T then
      {F H}
      {ForEach T F}
   end
end
{ForEach [57 321 88] proc {$ X} {Browse X} end}

% 2.2.2 Hierarchical Data and the Closure Property - Hierarchical Structures
fun {CountLeaves Tree}
   case Tree
   of nil then 0
   [] (H|S)|T then 1 + {CountLeaves S} + {CountLeaves T}
   [] H|T then 1 + {CountLeaves T}
   end
end

X2 = [[1 2] [3 4]]
{Browse {Length X2}}
{Browse {CountLeaves X2}}

% Mapping over trees
fun {ScaleTree Tree Factor}
   case Tree
   of nil then nil
   [] (H|S)|T then (H * Factor | {ScaleTree S Factor}) | {ScaleTree T Factor}
   [] H|T then H * Factor | {ScaleTree T Factor}
   end
end

{Browse {ScaleTree [1 [2 [3 4] 5] [6 7]] 10}}

fun {ScaleTree2 Tree Factor}
   {Map
      Tree
      fun {$ SubTree}
         case SubTree
         of H|T then {ScaleTree2 SubTree Factor}
         else SubTree * Factor
         end
      end}
end

% Exercise 2.24
{Browse [1 [2 [3 4]]]}

% Exercise 2.25
{Browse [1 3 [5 7] 9]}
{Browse [[7]]}
{Browse [1 [2 [3 [4 [5 [6 7]]]]]]}

% Exercise 2.26
X3 = [1 2 3]
Y3 = [4 5 6]
{Browse {Append X3 Y3}}
{Browse X3|Y3}
{Browse [X3 Y3]}

% Exercise 2.27
fun {DeepReverse L}
   case L
   of nil then nil
   [] H|T then
      if {IsList H} then
         {Append {DeepReverse T} [{DeepReverse H}]}
      else
         {Append {DeepReverse T} [H]}
      end
   end
end
X4 = [[1 2] [3 4]]
{Browse X4}
{Browse {Reverse X4}}
{Browse {DeepReverse X4}}

% Exercise 2.28
fun {Fringe L}
   case L
   of nil then nil
   [] H|T then
      if {IsList H} then
         {Append {Fringe H} {Fringe T}}
      else
         H|{Fringe T}
      end
   end
end
X5 = [[1 2] [3 4]]
{Browse {Fringe X5}}
{Browse {Fringe [X5 X5]}}

% Exercise 2.29
% List-based representation
% a.
fun {MakeMobile Left Right} [Left Right] end
fun {MakeBranch Length Struct} [Length Struct] end
fun {LeftBranch Mobile} Mobile.1 end
fun {RightBranch Mobile} Mobile.2.1 end
fun {BranchLength Branch} Branch.1 end
fun {BranchStruct Branch} Branch.2.1 end

% Helpers for b. and c.
fun {BranchWeight Branch}
   local
      Struct = {BranchStruct Branch}
   in
      if {IsList Struct} then
         {BranchWeight {LeftBranch Struct}} + {BranchWeight {RightBranch Struct}}
      else
         Struct
      end
   end
end

% b.
fun {TotalWeight Mobile}
   {BranchWeight {LeftBranch Mobile}} + {BranchWeight {RightBranch Mobile}}
end

% c.
fun {IsMobileBalanced Mobile}
   L = {LeftBranch Mobile}
   R = {RightBranch Mobile}
   Lmwl = {BranchLength L} * {BranchWeight L}
   Rmwl = {BranchLength R} * {BranchWeight R}
in
   if Lmwl == Rmwl then
      if {IsList {BranchStruct L}} andthen {IsList {BranchStruct R}} then
         {IsMobileBalanced {BranchStruct L}} andthen  {IsMobileBalanced {BranchStruct R}}
      elseif {IsList {BranchStruct L}} then
         {IsMobileBalanced {BranchStruct L}}
      elseif {IsList {BranchStruct R}} then
         {IsMobileBalanced {BranchStruct R}}
      else
         true
      end
   else
      false
   end
end

M1 = {MakeMobile {MakeBranch 10 100}
                 {MakeBranch 10 {MakeMobile {MakeBranch 40 20}
                                            {MakeBranch 10 80}}}}
M2 = [[10 100] [10 [[40 20] [10 80]]]]
{Browse {TotalWeight M1}#{TotalWeight M2}}
{Browse {IsMobileBalanced M1}#{IsMobileBalanced M2}}

% d.
%fun {MakeMobile Left Right} Left#Right end
%fun {MakeBranch Length Struc} Length#Struc end
%fun {RightBranch Mobile} Mobile.2 end
%fun {BranchStruct Branch} Branch.2 end

% Exercise 2.30
fun {SquareTree Tree}
   case Tree
   of nil then nil
   [] H|T then
      if {IsList H} then
         {Append [{SquareTree H}] {SquareTree T}}
      else
         (H*H)|{SquareTree T}
      end
   end
end
{Browse {SquareTree [1 [2 [3 4] 5] [6 7]]}}
fun {SquareTree1 Tree}
   {Map Tree
      fun {$ SubTree}
         if {IsList SubTree} then
            {SquareTree1 SubTree}
         else
            SubTree*SubTree
         end
      end}
end
{Browse {SquareTree1 [1 [2 [3 4] 5] [6 7]]}}

% Exercise 2.31
fun {TreeMap Tree Proc}
   case Tree
   of nil then nil
   [] H|T then
      if {IsList H} then
         {Append [{TreeMap H Proc}] {TreeMap T Proc}}
      else
         {Proc H}|{TreeMap T Proc}
      end
   end
end
fun {SquareTree2 Tree}
   {TreeMap Tree fun {$ X} X * X end}
end
{Browse {SquareTree2 [1 [2 [3 4] 5] [6 7]]}}

% Exercise 2.32
fun {Subsets S}
   case S
   of nil then [nil]
   [] H|T then
      local
         Rest = {Subsets T}
      in
         {Append Rest {Map Rest fun {$ X} H|X end}}
      end
   end
end
{Browse {Subsets [1 2 3]}}


% Alternate Translation Using Records instead of lists
   local
      fun {LengthTree Tree}
         case Tree
         of node(L) then {Length L}
         [] leaf(X) then 1
         end
      end

      fun {CountLeaves Tree}
         case Tree
         of node(nil) then 0
         [] node(H|T) then {CountLeaves H} + {CountLeaves node(T)}
         [] leaf(X) then 1
         end
      end

      X2 = node([node([leaf(1) leaf(2)]) node([leaf(3) leaf(4)])])

      {Browse X2}
      {Browse {LengthTree X2}}
      {Browse {CountLeaves X2}}
      {Browse node([X2 X2])}
      {Browse {LengthTree node([X2 X2])}}
      {Browse {CountLeaves node([X2 X2])}}

      % Mapping over trees
      fun {ScaleTree Tree Factor}
         {Browse Tree}
         case Tree
         of leaf(X) then leaf(X * Factor)
         [] node(nil) then node(nil)
         [] node(H|T) then {ScaleTree H Factor} | {ScaleTree node(T) Factor}
         end
      end

      {Browse {ScaleTree node([leaf(1) node([leaf(2) node([leaf(3) leaf(4)]) leaf(5)]) node([leaf(6) leaf(7)])]) 10}}

      % Exercise 2.24
      {Browse node([leaf(1) node([leaf(2) node([leaf(3) leaf(4)])])])}

      % Exercise 2.25
      {Browse node([leaf(1) leaf(3) node([leaf(5) leaf(7)]) leaf(9)])}
      {Browse node([node([leaf(7)])])}
      {Browse node([leaf(1) node([leaf(2) node([leaf(3) node([leaf(4) node([leaf(5) node([leaf(6) leaf(7)])])])])])])}

      % Exercise 2.26
      fun {AppendTree Tree1 Tree2}
         case Tree1#Tree2
         of node(X)#leaf(Y) then {Append X [leaf(Y)]}
         [] leaf(X)#node(Y) then node(leaf(X)|Y)
         [] node(X)#node(Y) then node({Append X Y})
         [] leaf(X)#leaf(Y) then node([leaf(X) leaf(Y)])
         end
      end
      X3 = node([leaf(1) leaf(2) leaf(3)])
      Y3 = node([leaf(4) leaf(5) leaf(6)])
      {Browse {AppendTree X3 Y3}}
      {Browse node([X3 node(Y3)])}
      {Browse node([X3 Y3])}

      % Exercise 2.27
      fun {ReverseTree Tree}
         case Tree
         of leaf(X) then leaf(X)
         [] node(L) then node({Reverse L})
         end
      end
      fun {DeepReverseTree Tree}
         case Tree
         of leaf(X) then leaf(X)
         [] node(L) then node({Reverse {Map L DeepReverseTree}})
         end
      end
      X4 = node([node([leaf(1) leaf(2)]) node([leaf(3) leaf(4)])])
      {Browse X4}
      {Browse {ReverseTree X4}}
      {Browse {DeepReverseTree X4}}

      % Exercise 2.28
      fun {Fringe Tree}
         {Browse Tree}
         case Tree
         of leaf(X) then [X]
         [] node(nil) then nil
         [] node(H|T) then {Append {Fringe H} {Fringe node(T)}}
         end
      end
      X5 = node([node([leaf(1) leaf(2)]) node([leaf(3) leaf(4)])])
      {Browse {Fringe X5}}
      {Browse {Fringe node([X5 X5])}}

      % Exercise 2.29
      % Record-based representation
      % a.
      fun {MakeMobile Left Right} mobile(Left Right) end
      fun {MakeBranch Len Struct} branch(Len Struct) end
      fun {MakeWeight Weight} weight(Weight) end

      fun {LeftBranch Mobile=mobile(Left Right)} Left end
      fun {RightBranch Mobile=mobile(Left Right)} Right end
      fun {BranchLength Branch=branch(Len Struct)} Len end
      fun {BranchStruct Branch=branch(Len Struct)} Struct end

      % Helpers for b. and c.
      fun {BranchWeight Branch}
         case Branch
         of branch(Len mobile(Left Right)) then {BranchWeight Left} + {BranchWeight Right}
         [] branch(Len weight(Weight)) then Weight
         end
      end

      % b.
      fun {TotalWeight Mobile}
         {BranchWeight {LeftBranch Mobile}} + {BranchWeight {RightBranch Mobile}}
      end

      % c.
      fun {IsMobileBalanced Mobile}
         Lmwl = {BranchLength {LeftBranch Mobile}} * {BranchWeight {LeftBranch Mobile}}
         Rmwl = {BranchLength {RightBranch Mobile}} * {BranchWeight {RightBranch Mobile}}
      in
         if Lmwl == Rmwl then
            case Mobile
            of mobile(branch(_ M1=mobile(_ _)) branch(_ M2=mobile(_ _))) then {IsMobileBalanced M1} andthen {IsMobileBalanced M2}
            [] mobile(branch(_ M1=mobile(_ _)) _) then {IsMobileBalanced M1}
            [] mobile(_ branch(_ M2=mobile(_ _))) then {IsMobileBalanced M2}
            else true
            end
         else
            false
         end
      end

      M1 = {MakeMobile {MakeBranch 10 {MakeWeight 100}}
                       {MakeBranch 10 {MakeMobile {MakeBranch 40 {MakeWeight 20}}
                                                  {MakeBranch 10 {MakeWeight 80}}}}}
      M2 = mobile(branch(10 weight(100))
                  branch(10 mobile(branch(40 weight(20))
                                   branch(10 weight(80)))))
      {Browse {TotalWeight M1}#{TotalWeight M2}}
      {Browse {IsMobileBalanced M1}#{IsMobileBalanced M2}}

      % Exercise 2.30
      fun {NodeList node(Xs)} Xs end
      fun {SquareTree Tree}
         case Tree
         of leaf(X) then leaf(X * X)
         [] node(nil) then node(nil)
         [] node(H|T) then node({SquareTree H} | {NodeList {SquareTree node(T)}})
         end
      end
      {Browse {SquareTree node([leaf(1) node([leaf(2) node([leaf(3) leaf(4)]) leaf(5)]) node([leaf(6) leaf(7)])])}}
      fun {SquareTree1 Tree}
         case Tree
         of leaf(X) then leaf(X * X)
         [] node(L) then node({Map L SquareTree1})
         end
      end
      {Browse {SquareTree1 node([leaf(1) node([leaf(2) node([leaf(3) leaf(4)]) leaf(5)]) node([leaf(6) leaf(7)])])}}

      % Exercise 2.31
      fun {TreeMap Tree Proc}
         case Tree
         of leaf(X) then leaf({Proc X})
         [] node(L) then node({Map L fun {$ Y} {TreeMap Y Proc} end})
         end
      end
      fun {SquareTree2 Tree}
         {TreeMap Tree fun {$ X} X * X end}
      end
      {Browse {SquareTree2 node([leaf(1) node([leaf(2) node([leaf(3) leaf(4)]) leaf(5)]) node([leaf(6) leaf(7)])])}}
   in
      skip
   end

% 2.2.3 Hierarchical Data and the Closure Property - Sequences as Conventional Interfaces
fun {SumOddSquares Tree}
   case Tree
   of nil then 0
   [] (H|S)|T then {SumOddSquares H|S} + {SumOddSquares T}
   [] H|T then
      if {IsOdd H} == true then
         {Square H} + {SumOddSquares T}
      else
         {SumOddSquares T}
      end
   end
end

fun {EvenFibs N}
   fun {Next K}
      if K > N then
         nil
      else
         local
            F = {Fib K}
         in
            if {IsEven F} then
               F|{Next K+1}
            else
               {Next K+1}
            end
         end
      end
   end
in
   {Next 0}
end

% Sequence operations
{Browse {Map [1 2 3 4 5] Square}}

fun {Filter2 Sequence Predicate}
   case Sequence
   of nil then nil
   [] H|T then
      if {Predicate H} then
         H|{Filter2 T Predicate}
      else
         {Filter2 T Predicate}
      end
   end
end

{Browse {Filter2 [1 2 3 4 5] IsOdd}}

% Accumulate is equivalent to FoldR
fun {Accumulate Sequence Oper Initial}
   case Sequence
   of nil then Initial
   [] H|T then {Oper H {Accumulate T Oper Initial}}
   end
end
{Browse {Accumulate [1 2 3 4 5] Number.'+' 0}}
{Browse {Accumulate [1 2 3 4 5] Number.'*' 1}}
{Browse {Accumulate [1 2 3 4 5] fun {$ A B} A | B end nil}}

fun {EnumerateInterval Low High}
   if Low > High then
      nil
   else
      Low | {EnumerateInterval Low+1 High}
   end
end

{Browse {EnumerateInterval 2 7}}

fun {EnumerateTree Tree}
   case Tree
   of nil then nil
   [] (H|S)|T then {Append {EnumerateTree H|S} {EnumerateTree T}}
   [] H|T then H|{EnumerateTree T}
   end
end

{Browse {EnumerateTree [1 [2 [3 4] 5]]}}

fun {SumOddSquares2 Tree}
   {Accumulate {Map {Filter {EnumerateTree Tree} IsOdd} Square} Number.'+' 0}
end

{Browse {SumOddSquares2 [1 [2 [3 4] 5]]}}

fun {EvenFibs2 N}
   {Accumulate
      {Filter {Map {EnumerateInterval 0 N} Fib} IsEven}
      fun {$ A B} A | B end
      nil}
end

{Browse {EvenFibs2 10}}

fun {ListFibSquares N}
   {Accumulate
      {Map {Map {EnumerateInterval 0 N} Fib} Square}
      fun {$ A B} A | B end
      nil}
end

{Browse {ListFibSquares 10}}

fun {ProductOfSquaresOfOddElements Sequence}
   {Accumulate {Map {Filter Sequence IsOdd} Square} Number.'*' 1}
end

{Browse {ProductOfSquaresOfOddElements [1 2 3 4 5]}}

fun {IsProgrammer Emp}
   case Emp
   of employee(jobtitle:X ...) then X == "Programmer"
   end
end
{Browse {IsProgrammer employee(name:"Fred" jobtitle:"Programmer" salary:180)}}

fun {Salary Emp}
   case Emp
   of employee(salary:X ...) then X
   end
end
{Browse {Salary employee(name:"Fred" jobtitle:"Programmer" salary:180)}}

fun {SalaryOfHighestPaidProgrammer Records}
   {Accumulate {Map {Filter Records IsProgrammer} Salary} Max 0}
end

Recs = [employee(name:"Fred" jobtitle:"Programmer" salary:180)
        employee(name:"Hank" jobtitle:"Programmer" salary:150)]

{Browse {SalaryOfHighestPaidProgrammer Recs}}

% Nested mappings
N = 10                   % book doesn't define N
{Browse
   {Accumulate
      {Map
         {EnumerateInterval 1 N}
         fun {$ I}
            {Map
               {EnumerateInterval 1 I-1}
               fun {$ J} [I J] end}
         end}
      Append
      nil}}

fun {Flatmap Seq Proc}
   {Accumulate {Map Seq Proc} Append nil}
end

fun {HasNoDivisors N C}
   case C
   of 1 then true
   else
      if N mod C == 0 then
         false
      else
         {HasNoDivisors N C-1}
      end
   end
end

fun {IsPrime N}
   {HasNoDivisors N N-1}
end

fun {PrimeSum L}
   case L
   of [X Y] then {IsPrime X+Y}
   end
end

fun {MakePairSum L}
   case L
   of [X Y] then [X Y X+Y]
   end
end

fun {PrimeSumPairs N}
   {Map
      {Filter
         {Flatmap
            {EnumerateInterval 1 N}
            fun {$ I}
               {Map
                  {EnumerateInterval 1 I-1}
                  fun {$ J} [I J] end}
            end}
         PrimeSum}
      MakePairSum}
end

fun {Remove Sequence Item}
   {Filter Sequence fun {$ X} X \= Item end}
end

fun {Permutations Seq}
   case Seq
   of nil then [nil]
   else
      {Flatmap
         Seq
         fun {$ X}
            {Map
               {Permutations {Remove Seq X}}
               fun {$ P} X|P end}
         end}
   end
end
{Browse {Permutations [1 2 3]}}

% Exercise 2.33
fun {Map2 Seq Proc}
   {Accumulate Seq fun {$ A B} {Proc A} | B end nil}
end
fun {Append2 Seq1 Seq2}
   {Accumulate Seq1 fun {$ A B} A|B end Seq2}
end
fun {Length3 Seq}
   {Accumulate Seq fun {$ X Y} Y+1 end 0}
end

% Exercise 2.34
fun {HornerEval C CoefficientSequence}
   {Accumulate
      CoefficientSequence
      fun {$ ThisCoeff HigherTerms}
         C*HigherTerms + ThisCoeff
      end
      0}
end
{Browse {HornerEval 2 [1 3 0 5 0 1]}}

% Exercise 2.35
fun {CountLeaves2 Tree}
   {Accumulate {Map {EnumerateTree Tree} fun {$ X} 1 end} Number.'+' 0}
 end
{Browse {CountLeaves2 X2}}

% Exercise 2.36
fun {AccumulateN Seq Oper Init}
   case Seq
   of nil|_ then nil
   else
      {Accumulate {Map Seq Head} Oper Init} |
         {AccumulateN {Map Seq Tail} Oper Init}
   end
end
{Browse {AccumulateN [[1 2 3] [4 5 6] [7 8 9] [10 11 12]] Number.'+' 0}}

% Exercise 2.37
% Still not quite right since won't handle multiply in nested arrays
fun {ExtendedMap L Proc}
   case L
   of (H1|T1)#(H2|T2) then {Proc H1 H2} | {ExtendedMap T1#T2 Proc}
   [] (H1|T1)#(H2|T2)#(H3|T3) then {Proc {Proc H1 H2} H3} | {ExtendedMap T1#T2#T3 Proc}
   else nil
   end
end
{Browse {ExtendedMap [1 2 3]#[40 50 60]#[700 800 900] Number.'+'}}

fun {DotProduct V W}
   {AccumulateN
      {Map V fun {$ L} {ExtendedMap L#W Number.'*'} end}
      Number.'+'
      0}
end
{Browse {DotProduct [[1 2 3 4] [4 5 6 6] [6 7 8 9]] [1 1 1 1]}}

fun {MatrixTimesVector M V}
   {Map M fun {$ Row} {DotProduct Row V} end}
end

fun {Transpose M}
   {AccumulateN M fun {$ A B} A|B end nil}
end

fun {MatrixTimesMatrix M N}
   Cols = {Transpose N}
in
   {Map M fun {$ Row} {MatrixTimesVector Cols Row} end}
end

% Exercise 2.38
FoldRight = Accumulate
fun {FoldLeft Sequence Oper Initial}
   fun {Iter L Result}
      case L
      of nil then Result
      [] H|T then {Iter T {Oper Result H}}
      end
   end
in
   {Iter Sequence Initial}
end
{Browse {FoldRight [1.0 2.0 3.0] Float.'/' 1.0}}
{Browse {FoldLeft  [1.0 2.0 3.0] Float.'/' 1.0}}
{Browse {FoldRight [1 2 3] fun {$ A B} A | B end nil}}
{Browse {FoldLeft [1 2 3] fun {$ A B} A | B end nil}}

% Exercise 2.39
fun {ReverseR Seq}
   {FoldR Seq fun {$ X Y} {Append Y [X]} end nil}
end
fun {ReverseL Seq}
   {FoldL Seq fun {$ X Y} Y | X end nil}
end
{Browse {ReverseR [1 2 3 4]}}
{Browse {ReverseL [1 2 3 4]}}

% Exercise 2.40
fun {UniquePairs N}
   {Flatmap
      {EnumerateInterval 1 N}
      fun {$ I}
         {Map
            {EnumerateInterval 1 I-1}
            fun {$ J} [I J] end}
      end
   }
end
fun {PrimeSumPairs_ N}
   {Map
      {Filter {UniquePairs N} PrimeSum}
      MakePairSum}
end

% Exercise 2.41
fun {UniqueTriples N}
   {Flatmap
      {EnumerateInterval 1 N}
      fun {$ I}
         {Flatmap
            {EnumerateInterval 1 I-1}
            fun {$ J}
               {Map
                  {EnumerateInterval 1 J-1}
                  fun {$ K} [I J K] end}
            end}
      end}
end
fun {TriplesSumS SumsTo N}
   {Filter
      {UniqueTriples N}
      fun {$ Triple}
         {Accumulate Triple Number.'+' 0} == SumsTo
      end}
end
{Browse {TriplesSumS 10 5}}

% Exercise 2.42
fun {Queens BoardSize}
   fun {QueenCols K}
      case K
      of 0 then [EmptyBoard]
      else
         {Filter
            {Flatmap
               {QueenCols K-1}
               fun {$ RestOfQueens}
                  {Map
                     {EnumerateInterval 1 BoardSize}
                     fun {$ NewRow}
                        {AdjoinPosition NewRow K RestOfQueens}
                     end}
               end}
            fun {$ Positions} {IsSafe K Positions} end}
      end
   end
in
   {QueenCols BoardSize}
end

EmptyBoard = nil

fun {AdjoinPosition NewRow K RestOfQueens}
   case RestOfQueens
   of nil then [K#NewRow]
   else (K#NewRow)|RestOfQueens
   end
end

fun {RemoveTargetColumn Column Board}
   {Filter Board fun {$ X} X.1 \= Column end}
end

fun {GetTargetColumn Column Board}
   {Head {Filter Board fun {$ X} X.1 == Column end}}
end

fun {IsCheck Pos1 Pos2}
   H1#T1 = Pos1
   H2#T2 = Pos2
in
   if H1 == H2 then
      true
   elseif T1 == T2 then
      true
   elseif {Abs H1-H2} == {Abs T1-T2} then
      true
   else
      false
   end
end

fun {BoardChecks Pos Board}
   case Board
   of nil then true
   [] H|T then
      if {IsCheck Pos H} then
         false
      else
         {BoardChecks Pos T}
      end
   end
end

fun {IsSafe X Y}
   {BoardChecks {GetTargetColumn X Y} {RemoveTargetColumn X Y}}
end

{Browse {Queens 4}}

% Exercise 2.43
fun {Queens_ BoardSize}
   fun {QueenCols K}
      case K
      of 0 then [EmptyBoard]
      else
         {Filter
            {Flatmap
               {EnumerateInterval 1 BoardSize}
               fun {$ NewRow}
                  {Map
                     {QueenCols K-1}
                     fun {$ RestOfQueens}
                        {AdjoinPosition NewRow K RestOfQueens}
                     end}
               end}
            fun {$ Positions} {IsSafe K Positions} end}
      end
   end
in
   {QueenCols BoardSize}
end

{Browse {Queens_ 4}}

% 2.2.4 Hierarchical Data and the Closure Property - Example: a picture language

% drawing primitives - output a postscript file
[File]={Module.link ['File.ozf']}
{File.writeOpen 'picture-lang.ps'}
PostscriptPageIndex = {NewCell 0}
{File.write "%!PS-Adobe-3.0\n"}
{File.write "%%Pages: 9\n\n"}              % note: I'm hard coding the number of postscript pages (9) that are generated below.
proc {Postscript Wave}
   PostscriptPageIndex := @PostscriptPageIndex + 1
   {File.write "%%Page: "}
   {File.write @PostscriptPageIndex}
   {File.write " "}
   {File.write @PostscriptPageIndex}
   {File.write "\n"}
   {File.write "/inch {72 8 mul mul} def\n"}
   {Wave {MakeFrame {MakeVect 0.0 0.0} {MakeVect 1.0 0.0} {MakeVect 0.0 1.0}}}
   {File.write "showpage\n"}
   {File.write "\n"}
end
proc {DrawLine X Y}
   {File.write "newpath\n"}
   case X#Y
   of (vect(x:X0 y:Y0))#(vect(x:X1 y:Y1)) then
      {File.write X0#" inch "#Y0#" inch moveto\n"}
      {File.write X1#" inch "#Y1#" inch lineto\n"}
   end
   {File.write "closepath\n"}
   {File.write "stroke\n"}
end

proc {Wave XFrame}
   Segs = [{MakeSegment_1 {MakeVect 0.40 1.00} {MakeVect 0.35 0.80}}
           {MakeSegment_1 {MakeVect 0.35 0.80} {MakeVect 0.40 0.60}}
           {MakeSegment_1 {MakeVect 0.40 0.60} {MakeVect 0.30 0.60}}
           {MakeSegment_1 {MakeVect 0.30 0.60} {MakeVect 0.20 0.55}}
           {MakeSegment_1 {MakeVect 0.20 0.55} {MakeVect 0.00 0.80}}
           {MakeSegment_1 {MakeVect 0.00 0.60} {MakeVect 0.20 0.45}}
           {MakeSegment_1 {MakeVect 0.20 0.45} {MakeVect 0.30 0.55}}
           {MakeSegment_1 {MakeVect 0.30 0.55} {MakeVect 0.35 0.50}}
           {MakeSegment_1 {MakeVect 0.35 0.50} {MakeVect 0.25 0.00}}
           {MakeSegment_1 {MakeVect 0.40 0.00} {MakeVect 0.50 0.20}}
           {MakeSegment_1 {MakeVect 0.50 0.20} {MakeVect 0.60 0.00}}
           {MakeSegment_1 {MakeVect 0.75 0.00} {MakeVect 0.65 0.50}}
           {MakeSegment_1 {MakeVect 0.65 0.50} {MakeVect 1.00 0.20}}
           {MakeSegment_1 {MakeVect 1.00 0.40} {MakeVect 0.70 0.60}}
           {MakeSegment_1 {MakeVect 0.70 0.60} {MakeVect 0.60 0.60}}
           {MakeSegment_1 {MakeVect 0.60 0.60} {MakeVect 0.65 0.80}}
           {MakeSegment_1 {MakeVect 0.65 0.80} {MakeVect 0.60 1.00}}]
in
   {{SegmentsPainter Segs} XFrame}
end

fun {MakeVect X Y} vect(x:X y:Y) end
fun {XcorVect V} case V of vect(x:X ...) then X end end
fun {YcorVect V} case V of vect(y:Y ...) then Y end end
fun {AddVect V1 V2} {MakeVect {XcorVect V1}+{XcorVect V2} {YcorVect V1}+{YcorVect V2}} end
fun {SubVect V1 V2} {MakeVect {XcorVect V1}-{XcorVect V2} {YcorVect V1}-{YcorVect V2}} end
fun {ScaleVect S V} {MakeVect S*{XcorVect V} S*{YcorVect V}} end

fun {MakeFrame Origin Edge1 Edge2} frame(origin:Origin edge1:Edge1 edge2:Edge2) end
fun {OriginFrame F} case F of frame(origin:Origin ...) then Origin end end
fun {Edge1Frame F} case F of  frame(edge1:Edge1 ...) then Edge1 end end
fun {Edge2Frame F} case F of  frame(edge2:Edge2 ...) then Edge2 end end
AFrame = {MakeFrame {MakeVect 0.0 0.0} {MakeVect 1.0 0.0} {MakeVect 0.0 1.0}}

fun {MakeSegment_1 StartSegment EndSegment} segment(x:StartSegment y:EndSegment) end
fun {StartSegment_1 S} case S of segment(x:X ...) then X end end
fun {EndSegment_1 S} case S of segment(y:Y ...) then Y end end

% Frames
fun {FrameCoordMap XFrame}
   fun {$ V}
      {AddVect
         {OriginFrame XFrame}
         {AddVect
            {ScaleVect {XcorVect V} {Edge1Frame XFrame}}
            {ScaleVect {YcorVect V} {Edge2Frame XFrame}}}}
   end
end

_ = {{FrameCoordMap AFrame} {MakeVect 0.0 0.0}}
_ = {OriginFrame AFrame}

% Painters
fun {SegmentsPainter SegmentList}
   proc {$ XFrame}
      {ForEach
         SegmentList
         proc {$ Segment}
            {DrawLine
               {{FrameCoordMap XFrame} {StartSegment_1 Segment}}
               {{FrameCoordMap XFrame} {EndSegment_1 Segment}}}
         end}
   end
end

{Postscript Wave}

fun {TransformPainter Painter Origin Corner1 Corner2}
   proc {$ XFrame}
      M = {FrameCoordMap XFrame}
      NewOrigin = {M Origin}
   in
      {Painter
         {MakeFrame
            NewOrigin
            {SubVect {M Corner1} NewOrigin}
            {SubVect {M Corner2} NewOrigin}}}
   end
end

fun {FlipVert Painter}
   {TransformPainter
      Painter
      {MakeVect 0.0 1.0}
      {MakeVect 1.0 1.0}
      {MakeVect 0.0 0.0}}
end

fun {ShrinkToUpperRight Painter}
   {TransformPainter
      Painter
      {MakeVect 0.5 0.5}
      {MakeVect 1.0 0.5}
      {MakeVect 0.5 1.0}}
end

fun {Rotate90 Painter}
   {TransformPainter
      Painter
      {MakeVect 1.0 0.0}
      {MakeVect 1.0 1.0}
      {MakeVect 0.0 0.0}}
end

fun {SquashInwards Painter}
   {TransformPainter
      Painter
      {MakeVect 0.0 0.0}
      {MakeVect 0.65 0.35}
      {MakeVect 0.35 0.65}}
end

fun {Beside Painter1 Painter2}
   proc {$ XFrame}
      SplitPoint = {MakeVect 0.5 0.0}
      PaintLeft =
         {TransformPainter
            Painter1
            {MakeVect 0.0 0.0}
            SplitPoint
            {MakeVect 0.0 1.0}}
      PaintRight =
         {TransformPainter
            Painter2
            SplitPoint
            {MakeVect 1.0 0.0}
            {MakeVect 0.5 1.0}}
   in
      {PaintLeft XFrame}
      {PaintRight XFrame}
   end
end

fun {Below Painter1 Painter2}
   proc {$ XFrame}
      SplitPoint = {MakeVect 0.0 0.5}
      PaintBelow =
         {TransformPainter
            Painter1
            {MakeVect 0.0 0.0}
            {MakeVect 1.0 0.0}
            SplitPoint}
      PaintAbove =
         {TransformPainter
            Painter2
            SplitPoint
            {MakeVect 1.0 0.5}
            {MakeVect 0.0 1.0}}
   in
      {PaintBelow XFrame}
      {PaintAbove XFrame}
   end
end

Wave2 = {Beside Wave {FlipVert Wave}}
Wave4 = {Below Wave2 Wave2}

{Postscript Wave2}
{Postscript Wave4}

fun {FlippedPairs Painter}
   Painter2 = {Beside Painter {FlipVert Painter}}
in
   {Below Painter2 Painter2}
end

Wave4_ = {FlippedPairs Wave}
{Postscript Wave4_}

fun {RightSplit Painter N}
   case N
   of 0 then Painter
   else
      local
         Smaller = {RightSplit Painter N-1}
      in
         {Beside Painter {Below Smaller Smaller}}
      end
   end
end

fun {CornerSplit Painter N}
   case N
   of 0 then Painter
   else
      local
         Up = {UpSplit Painter N-1}
         Right = {RightSplit Painter N-1}
         TopLeft = {Beside Up Up}
         BottomRight = {Below Right Right}
         Corner = {CornerSplit Painter N-1}
      in
         {Beside {Below Painter TopLeft} {Below BottomRight Corner}}
      end
   end
end

fun {SquareLimit Painter N}
   Quarter = {CornerSplit Painter N}
   Half = {Beside {FlipHoriz Quarter} Quarter}
in
   {Below {FlipVert Half} Half}
end

% Higher_order operations
fun {SquareOfFour TLeft TRight BLeft BRight}
   fun {$ Painter}
      Top = {Beside {TLeft Painter} {TRight Painter}}
      Bottom = {Beside {BLeft Painter} {BRight Painter}}
   in
      {Below Bottom Top}
   end
end

fun {FlippedPairs2 Painter}
   Combine4 = {SquareOfFour Identity FlipVert Identity FlipVert}
in
   {Combine4 Painter}
end

% footnote
FlippedPairs3 = {SquareOfFour Identity FlipVert Identity FlipVert}

fun {SquareLimit2 Painter N}
   Combine4 = {SquareOfFour FlipHoriz Identity Rotate180 FlipVert}
in
   {Combine4 {CornerSplit Painter N}}
end

% Exercise 2.44
fun {UpSplit Painter N}
   case N
   of 0 then Painter
   else
      local
         Smaller = {UpSplit Painter N-1}
      in
         {Below Painter {Beside Smaller Smaller}}
      end
   end
end
{Postscript {UpSplit Wave 4}}

% Exercise 2.45
fun {Split CombineMain CombineSmaller}
   fun {$ Painter N}
      if N == 0 then
         Painter
      else
         local
            Smaller = {{Split CombineMain CombineSmaller} Painter N-1}
         in
            {CombineMain Painter {CombineSmaller Smaller Smaller}}
         end
      end
   end
end
RightSplit_ = {Split Beside Below}
UpSplit_ = {Split Below Beside}
{Postscript {UpSplit_ Wave 4}}
{Postscript {RightSplit_ Wave 4}}

% Exercise 2.46
fun {MakeVect_ X Y} X#Y end
fun {XcorVect_ X#Y} X end
fun {YcorVect_ X#Y} Y end
fun {AddVect_ V1 V2}
   {MakeVect_ {XcorVect_ V1}+{XcorVect_ V2} {YcorVect_ V1}+{YcorVect_ V2}}
end
fun {SubVect_ V1 V2}
   {MakeVect_ {XcorVect_ V1}-{XcorVect_ V2} {YcorVect_ V1}-{YcorVect_ V2}}
end
fun {ScaleVect_ S V}
   {MakeVect_ S*{XcorVect_ V} S*{YcorVect_ V}}
end

% Exercise 2.47
fun {MakeFrame2 Origin Edge1 Edge2} [Origin Edge1 Edge2] end
fun {MakeFrame3 Origin Edge1 Edge2} [Origin [Edge1 Edge2]] end

fun {OriginFrame2 F} F.1 end
fun {Edge1Frame2 F} F.2.1 end
fun {Edge2Frame2 F} F.2.2.1 end

fun {OriginFrame3 F} F.1 end
fun {Edge1Frame3 F} F.2.1.1 end
fun {Edge2Frame3 F} F.2.1.2.1 end

% Exercise 2.48
fun {MakeSegment_ VStart VEnd} VStart#VEnd end
fun {StartSegment_ VStart#VEnd} VStart end
fun {EndSegment_ VStart#VEnd} VEnd end

% Exercise 2.49
proc {Outline XFrame}
   Segs = [{MakeSegment_1 {MakeVect 0.0 0.0} {MakeVect 0.0 1.0}}
           {MakeSegment_1 {MakeVect 0.0 0.0} {MakeVect 1.0 0.0}}
           {MakeSegment_1 {MakeVect 1.0 0.0} {MakeVect 1.0 1.0}}
           {MakeSegment_1 {MakeVect 0.0 1.0} {MakeVect 1.0 1.0}}]
in
   {{SegmentsPainter Segs} XFrame}
end
proc {XXX XFrame}
   Segs = [{MakeSegment_1 {MakeVect 1.0 0.0} {MakeVect 0.0 1.0}}
           {MakeSegment_1 {MakeVect 0.0 0.0} {MakeVect 1.0 1.0}}]
in
   {{SegmentsPainter Segs} XFrame}
end

proc {Diamond XFrame}
   Segs = [{MakeSegment_1 {MakeVect 0.5 0.0} {MakeVect 1.0 0.5}}
           {MakeSegment_1 {MakeVect 1.0 0.5} {MakeVect 0.5 1.0}}
           {MakeSegment_1 {MakeVect 0.0 0.5} {MakeVect 0.5 0.0}}
           {MakeSegment_1 {MakeVect 0.0 0.5} {MakeVect 0.5 1.0}}]
in
   {{SegmentsPainter Segs} XFrame}
end
{Postscript {Below {Beside Outline XXX} {Beside Diamond Wave}}}

% Exercise 2.50
fun {FlipHoriz Painter}
   {TransformPainter
      Painter
      {MakeVect 1.0 0.0}
      {MakeVect 0.0 0.0}
      {MakeVect 1.0 1.0}}
end
fun {Rotate180 Painter}
   {TransformPainter
      Painter
      {MakeVect 1.0 1.0}
      {MakeVect 0.0 1.0}
      {MakeVect 1.0 0.0}}
end
fun {Rotate270 Painter}
   {TransformPainter
      Painter
      {MakeVect 1.0 0.0}
      {MakeVect 1.0 1.0}
      {MakeVect 0.0 0.0}}
end

% Exercise 2.51
% see definition of Below given above
fun {BelowRot Painter1 Painter2}
   {Rotate90 {Beside {Rotate270 Painter1} {Rotate270 Painter2}}}
end

% Exercise 2.52
% see definition of CornerSplit given above
{Postscript {SquareLimit Wave 4}}

{File.writeClose}

% 2.3.1 Symbolic Data - Quotation

% To Be Done.


% 2.3.2 Symbolic Data - Example: Symbolic Differentiation

fun {IsSameNumber X Y}
   {IsNumber X} andthen {IsNumber Y} andthen X == Y
end

fun {IsVariable X}
   {IsAtom X}
end

fun {IsSameVariable X Y}
   {IsVariable X} andthen {IsVariable Y} andthen X == Y
end

fun {IsSum L}
   case L
   of sum(...) then true
   else false
   end
end

fun {IsProduct L}
   case L
   of product(...) then true
   else false
   end
end

fun {MakeSum X Y}
   if {IsNumber X} andthen {IsNumber Y} then
      X + Y
   else
      sum(X Y)
   end
end

fun {MakeProduct X Y}
   if {IsNumber X} andthen {IsNumber Y} then
      X * Y
   else
      product(X Y)
   end
end

fun {AddEnd L}
   case L
   of sum(X ...) then X
   else raise invalid('a - Invalid pattern match ' # L) end
   end
end

fun {AugEnd L}
   case L
   of sum(_ Y) then Y
   else raise invalid('b - Invalid pattern match ' # L) end
   end
end

fun {Multiplier L}
   case L
   of product(X ...) then X
   else raise invalid('c - Invalid pattern match ' # L) end
   end
end

fun {Multiplicand L}
   case L
   of product(_ Y) then Y
   else raise invalid('d - Invalid pattern match ' # L) end
   end
end

fun {Deriv Expr Var}
   if {IsNumber Expr} then
      0
   elseif {IsVariable Expr} then
      if {IsSameVariable Expr Var} then
         1
      else
         0
      end
   elseif {IsSum Expr} then
      {MakeSum {Deriv {AddEnd Expr} Var}
               {Deriv {AugEnd Expr} Var}}
   elseif {IsProduct Expr} then
      {MakeSum {MakeProduct {Multiplier Expr} {Deriv {Multiplicand Expr} Var}}
               {MakeProduct {Deriv {Multiplier Expr} Var} {Multiplicand Expr}}}
   else raise invalid('Invalid Exprression ' # Expr) end
   end
end

% dx(x + 3) = 1
{Browse {Deriv sum(x 3) x}}

% dx(x*y) = y
{Browse {Deriv product(x y) x}}

% dx(x*y + x + 3) = y + 1
{Browse {Deriv sum(sum(product(x y) x) 3) x}}

% with simplification
fun {MakeSum1 X Y}
   if {IsNumber X} andthen X == 0 then
      Y
   elseif {IsNumber Y} andthen Y == 0 then
      X
   elseif {IsNumber X} andthen {IsNumber Y} then
      X + Y
   else
      sum(X Y)
   end
end

fun {MakeProduct1 X Y}
   if {IsNumber X} andthen X == 0 then
      0
   elseif {IsNumber Y} andthen Y == 0 then
      0
   elseif {IsNumber X} andthen X == 1 then
      Y
   elseif {IsNumber Y} andthen Y == 1 then
      X
   elseif {IsNumber X} andthen {IsNumber Y} then
      X * Y
   else
      product(X Y)
   end
end

fun {Deriv1 Expr Var}
   if {IsNumber Expr} then
      0
   elseif {IsVariable Expr} then
      if {IsSameVariable Expr Var} then
         1
      else
         0
      end
   elseif {IsSum Expr} then
      {MakeSum1 {Deriv1 {AddEnd Expr} Var}
                {Deriv1 {AugEnd Expr} Var}}
   elseif {IsProduct Expr} then
      {MakeSum1 {MakeProduct1 {Multiplier Expr} {Deriv1 {Multiplicand Expr} Var}}
                {MakeProduct1 {Deriv1 {Multiplier Expr} Var} {Multiplicand Expr}}}
   else
      raise invalid('Invalid Exprression ' # Expr) end
   end
end

% dx(x + 3) = 1
{Browse {Deriv1 sum(x 3) x}}

% dx(x*y) = y
{Browse {Deriv1 product(x y) x}}

% dx(x*y + x + 3) = y + 1
{Browse {Deriv1 sum(sum(product(x y) x) 3) x}}

% Exercise 2.56
fun {MakeExponentiation Base Exp}
   if {IsNumber Exp} andthen Exp == 0 then
      1
   elseif {IsNumber Exp} andthen Exp == 1 then
      Base
   elseif {IsNumber Exp} andthen {IsNumber Base} then
      {Pow Base Exp}
   else
      power(Base Exp)
   end
end

fun {IsExponentiation L}
   case L
   of power(X Y) then true
   else false
   end
end

fun {Base L}
   case L
   of power(X _) then X
   else raise invalid('e - Invalid pattern match ' # L) end
   end
end

fun {Exponent L}
   case L
   of power(_ Y) then Y
   else raise invalid('f - Invalid pattern match ' # L) end
   end
end

fun {Deriv2 Expr Var}
   if {IsNumber Expr} then
      0
   elseif {IsVariable Expr} then
      if {IsSameVariable Expr Var} then
         1
      else
         0
      end
   elseif {IsExponentiation Expr} then
      {MakeProduct1 {MakeProduct1 {Exponent Expr}
                                  {MakeExponentiation {Base Expr} {MakeSum1 {Exponent Expr} ~1}}}
                    {Deriv2 {Base Expr} Var}}
   elseif {IsSum Expr} then
      {MakeSum1 {Deriv2 {AddEnd Expr} Var}
                {Deriv2 {AugEnd Expr} Var}}
   elseif {IsProduct Expr} then
      {MakeSum1 {MakeProduct1 {Multiplier Expr} {Deriv2 {Multiplicand Expr} Var}}
                {MakeProduct1 {Deriv2 {Multiplier Expr} Var} {Multiplicand Expr}}}
   else
      raise invalid('Invalid Exprression ' # Expr) end
   end
end

% Exercise 2.57
fun {AugEnd2 L}
   case L
   of sum(_ Y) then Y
   [] sum(_ Y ...) then {List.toTuple {Label L} {Record.toList L}.2}
   else raise invalid('g - Invalid pattern match ' # L) end
   end
end

fun {Multiplicand2 L}
   case L
   of product(_ Y) then Y
   [] product(_ Y ...) then {List.toTuple {Label L} {Record.toList L}.2}
   else raise invalid('h - Invalid pattern match ' # L) end
   end
end

fun {Deriv3 Expr Var}
   if {IsNumber Expr} then
      0
   elseif {IsVariable Expr} then
      if {IsSameVariable Expr Var} then
         1
      else
         0
      end
   elseif {IsExponentiation Expr} then
      {MakeProduct1 {MakeProduct1 {Exponent Expr}
                                  {MakeExponentiation {Base Expr} {MakeSum1 {Exponent Expr} ~1}}}
                    {Deriv3 {Base Expr} Var}}
   elseif {IsSum Expr} then
      {MakeSum1 {Deriv3 {AddEnd Expr} Var}
                {Deriv3 {AugEnd2 Expr} Var}}
   elseif {IsProduct Expr} then
      {MakeSum1 {MakeProduct1 {Multiplier Expr} {Deriv3 {Multiplicand2 Expr} Var}}
                {MakeProduct1 {Deriv3 {Multiplier Expr} Var} {Multiplicand2 Expr}}}
   else
      raise invalid('Invalid Exprression ' # Expr) end
   end
end

% dx(x*y*(x+3)) = dx(x*x*y + 3*x*y) = 2xy + 3y
{Browse {Deriv3 sum(product(x x y) product(3 x y)) x}}

% Exercise 2.58
% To Be Done

% 2.3.3 Symbolic Data - Example: Representing Sets

% unordered
fun {IsElementOfSet X L}
   case L
   of nil then false
   [] H|T then
      if X == H then
         true
      else
         {IsElementOfSet X T}
      end
   end
end

fun {AdjoinSet X Set}
   if {IsElementOfSet X Set} then
      Set
   else
      X|Set
   end
end

fun {IntersectionSet Set1 Set2}
   case Set1#Set2
   of nil#_ then nil
   [] _#nil then nil
   [] (H|T)#_ then
      if {IsElementOfSet H Set2} then
         H|{IntersectionSet T Set2}
      else
         {IntersectionSet T Set2}
      end
   end
end

% ordered
fun {IsElementOfSet1 X L}
   case L
   of nil then false
   [] H|T then
      if X == H then
         true
      else
         if X < H then
            false
         else
            {IsElementOfSet1 X T}
         end
      end
   end
end

fun {IntersectionSet1 Set1 Set2}
   case Set1#Set2
   of nil#_ then nil
   [] _#nil then nil
   [] (X|Xs)#(Y|Ys) then
      if X == Y then
         X|{IntersectionSet1 Xs Ys}
      elseif X < Y then
         {IntersectionSet1 Xs Set2}
      else
         {IntersectionSet1 Set1 Ys}
      end
   end
end

% Sets as binary trees
fun {IsElementOfSet2 X Node}
   case Node
   of leaf then false
   [] tree(Y Left Right) then
      if X == Y then
         true
      else
         if X < Y then
            {IsElementOfSet2 X Left}
         else
            {IsElementOfSet2 X Right}
         end
      end
   end
end

{Browse {IsElementOfSet2 3 tree(2 tree(1 leaf leaf) tree(3 leaf leaf))}}

fun {AdjoinSet2 X Node}
   case Node
   of leaf then tree(X leaf leaf)
   [] tree(Y Left Right) then
      if X == Y then
         Node
      else
         if X < Y then
            tree(Y {AdjoinSet2 X Left} Right)
         else
            tree(Y Left {AdjoinSet2 X Right})
         end
      end
   end
end

{Browse {AdjoinSet2 3 tree(4 tree(2 leaf leaf) tree(6 leaf leaf))}}

% information retrieval
fun {Lookup GivenKey L}
   case L
   of information(Key Name Age)|T then
      if GivenKey == Key then
         L.1
      else
         {Lookup GivenKey T}
      end
   else raise invalid('Invalid pattern match ' # L) end
   end
end

% Exercise 2.59
fun {UnionSet Set1 Set2}
   {Append
      Set1
      {Filter Set2 fun {$ X} {Not {IsElementOfSet X Set1}} end}}
end
{Browse {UnionSet [3 1 2] [4 3 2 5]}}

% Exercise 2.60
fun {IsElementOfMultiSet X L}
   {Member X L}
end
fun {IntersectionMultiSet Set1 Set2}
   case Set1#Set2
   of (X|Xs)#(Y|Ys) then
      if {IsElementOfMultiSet X Set2} then
         X|{IntersectionMultiSet Xs Set2}
      else
         {IntersectionMultiSet Xs Set2}
      end
   else nil
   end
end
fun {AdjoinMultiSet X Set}
   X|Set
end
fun {UnionMultiSet Set1 Set2}
   {Append Set1 Set2}
end
{Browse {IsElementOfMultiSet 3 [2 3 2 1 3 2 2]}}
{Browse {IntersectionMultiSet [2 3 2 1 3 2 2] [4 2 3 2 5]}}
{Browse {AdjoinMultiSet 5 [2 3 2 1 3 2 2]}}
{Browse {UnionMultiSet [2 3 2 1 3 2 2] [4 2 3 2 5]}}

% Exercise 2.61
fun {AdjoinSet1 X Set}
   case Set
   of nil then [X]
   [] H|T then
      if H == X then
         Set
      elseif H > X then
         X|Set
      else
         H|{AdjoinSet1 X T}
      end
   end
end
{Browse {AdjoinSet1 3 [2 4 6]}}

% Exercise 2.62
fun {UnionSet1 Set1 Set2}
   case Set1#Set2
   of _#nil then Set1
   [] nil#_ then Set2
   [] (X|Xs)#(Y|Ys) then
      if X == Y then
         X|{UnionSet1 Xs Ys}
      elseif X < Y then
         X|{UnionSet1 Xs Set2}
      else
         Y|{UnionSet1 Set1 Ys}
      end
   end
end
{Browse {UnionSet1 [1 2 3] [2 3 4 5]}}

% Exercise 2.63
fun {TreeToList1 Node}
   case Node
   of leaf then nil
   [] tree(Y Left Right) then
      {Append {TreeToList1 Left} Y|{TreeToList1 Right}}
   end
end
{Browse {TreeToList1 tree(4 tree(2 leaf leaf) tree(6 leaf leaf))}}

fun {TreeToList2 Node}
   fun {CopyToList T L}
      case T
      of leaf then L
      [] tree(X Left Right) then
         {CopyToList Left X|{CopyToList Right L}}
      end
   end
in
   {CopyToList Node nil}
end
{Browse {TreeToList2 tree(4 tree(2 leaf leaf) tree(6 leaf leaf))}}

% Exercise 2.64
fun {PartialTree Elts N}
   if N == 0 then
      leaf#Elts
   else
      local
         LeftSize = (N-1) div 2
         RightSize = N - (LeftSize + 1)
         LeftResult = {PartialTree Elts LeftSize}
         LeftTree#NonLeftElts = LeftResult
         ThisEntry = NonLeftElts.1
         RightResult = {PartialTree NonLeftElts.2 RightSize}
         RightTree#RemainingElts = RightResult
      in
         tree(ThisEntry LeftTree RightTree)#RemainingElts
      end
   end
end

fun {ListToTree Elements}
   Result#_ = {PartialTree Elements {Length Elements}}
in
   Result
end

{Browse {ListToTree [2 4 6]}}

% Exercise 2.65
fun {UnionSetBinTree Set1 Set2}
   {ListToTree {UnionSet {TreeToList2 Set1} {TreeToList2 Set2}}}
end
fun {IntersectionSetBinTree Set1 Set2}
   {ListToTree {IntersectionSet {TreeToList2 Set1} {TreeToList2 Set2}}}
end

% Exercise 2.66
fun {Lookup1 GivenKey Tree}
   case Tree
   of tree(Item=information(Key Name Age) Left Right) then
      if GivenKey == Key then
         Item
      elseif GivenKey < Key then
         {Lookup GivenKey Left}
      else
         {Lookup GivenKey Right}
      end
   else raise invalid('Invalid pattern match ' # GivenKey) end
   end
end

% 2.3.4 Symbolic Data - Example: Huffman Encoding Trees

fun {MakeLeaf Symbol Weight}
   leaf(Symbol Weight)
end

fun {IsLeaf Node}
   case Node
   of leaf(_ _) then true
   else false
   end
end

fun {SymbolLeaf Node}
   case Node
   of leaf(Symbol _) then Symbol
   else raise invalid('Invalid pattern match ' # Node) end
   end
end

fun {WeightLeaf Node}
   case Node
   of leaf(_ Weight) then Weight
   else raise invalid('Invalid pattern match ' # Node) end
   end
end

fun {Symbols Node}
   case Node
   of leaf(Symbol _) then [Symbol]
   [] tree(SubSymbols _ _ _) then SubSymbols
   end
end

fun {Weight Node}
   case Node
   of leaf(_ Weight) then Weight
   [] tree(_ Weight _ _) then Weight
   end
end

fun {MakeCodeTree Left Right}
   tree(
      {Append {Symbols Left} {Symbols Right}}
      ({Weight Left} + {Weight Right})
      Left
      Right)
end

fun {LeftNode Node}
   case Node
   of tree(_ _ Left _) then Left
   else raise invalid('Invalid pattern match ' # Node) end
   end
end
fun {RightNode Node}
   case Node
   of tree(_ _ _ Right) then Right
   else raise invalid('Invalid pattern match ' # Node) end
   end
end

fun {ChooseNode N Node}
   case N
   of 0 then {LeftNode Node}
   [] 1 then {RightNode Node}
   else raise invalid('Invalid pattern match ' # N) end
   end
end

% decoding
fun {Decode Bits Tree}
   fun {Decode_1 Bits CurrentNode}
      case Bits
      of nil then nil
      [] H|T then
         local
            NextNode = {ChooseNode H CurrentNode}
         in
            if {IsLeaf NextNode} then
               {SymbolLeaf NextNode} | {Decode_1 T Tree}
            else
               {Decode_1 T NextNode}
            end
         end
      end
   end
in
   {Decode_1 Bits Tree}
end

% sets
fun {AdjoinSet3 X Set}
   case Set
   of nil then [X]
   [] H|T then
      if {Weight X} < {Weight H} then
         X|Set
      else
         H|{AdjoinSet3 X T}
      end
   end
end

fun {MakeLeafSet Node}
   case Node
   of (Symbol#Weight)|Pairs then {AdjoinSet3 {MakeLeaf Symbol Weight} {MakeLeafSet Pairs}}
   [] nil then nil
   else raise invalid('Invalid pattern match ' # Node) end
   end
end

% Exercise 2.67
SampleTree = {MakeCodeTree
      {MakeLeaf &A 4}
      {MakeCodeTree
         {MakeLeaf &B 2}
         {MakeCodeTree
            {MakeLeaf &D 1}
            {MakeLeaf &C 1}}}}
SampleMessage = [0 1 1 0 0 1 0 1 0 1 1 1 0]
{Browse {StringToAtom {Decode SampleMessage SampleTree}}}

% Exercise 2.68
fun {EncodeSymbol C Tree}
   if {Member C {Symbols Tree}} then
      local
         L = {LeftNode Tree}
         R = {RightNode Tree}
      in
         if {IsLeaf L} andthen C == {SymbolLeaf L} then
            [0]
         elseif {IsLeaf R} andthen C == {SymbolLeaf R} then
            [1]
         elseif {Not {IsLeaf L}} andthen {Member C {Symbols L}} then
            0|{EncodeSymbol C L}
         elseif {Not {IsLeaf R}} andthen {Member C {Symbols R}} then
            1|{EncodeSymbol C R}
         end
      end
   else
      raise encodingXXX end
   end
end
fun {Encode Message Tree}
   case Message
   of nil then nil
   [] H|T then {Append {EncodeSymbol H Tree} {Encode T Tree}}
   end
end
{Browse {StringToAtom {Decode {Encode "ADABBCA" SampleTree} SampleTree}}}

% Exercise 2.69
fun {GenerateHuffmanTree Pairs}
   {SuccessiveMerge {MakeLeafSet Pairs}}
end
fun {SuccessiveMerge NodeSet}
   case NodeSet
   of H|nil then H
   [] H|S|T then {SuccessiveMerge {AdjoinSet3 {MakeCodeTree H S} T}}
   end
end
{Browse {GenerateHuffmanTree [&A#8 &B#3 &C#1 &D#1 &E#1 &F#1 &G#1 &H#1]}}

% Exercise 2.70
Rock50sTree = {GenerateHuffmanTree [a#2 boom#1 get#2 job#2 na#16 sha#3 yip#9 wah#1]}
{Browse {Length {Encode [get a job sha na na na na na na na na
                         get a job sha na na na na na na na na
                         wah yip yip yip yip yip yip yip yip yip
                         sha boom]
                        Rock50sTree}}}

% Exercise 2.71
% n = 5
{Browse  {GenerateHuffmanTree [a#1 b#2 c#4 d#8 e#16]}}
% n = 10
{Browse  {GenerateHuffmanTree [a#1 b#2 c#4 d#8 e#16 f#32 g#64 h#128 i#256 j#512]}}

% 2.4.1 Multiple Representations for Abstract Data - Representations for Complex Numbers

% Same as above
% fun {Square X} X * X end

% Rectangular
fun {RealPartR Real#_} Real end
fun {ImagPartR _#Imag} Imag end

fun {MagnitudeR Z} {Sqrt {Square {RealPartR Z}} + {Square {ImagPartR Z}}} end
fun {AngleR Z} {Atan2 {ImagPartR Z} {RealPartR Z}} end

fun {MakeFromRealImagR R I} R#I end
fun {MakeFromMagAngR M A} M*{Cos A}#M*{Sin A} end

% polar
fun {MagnitudeP Mag#_} Mag end
fun {AngleP _#Ang} Ang end

fun {RealPartP Z} {MagnitudeP Z} * {Cos {AngleP Z}} end
fun {ImagPartP Z} {MagnitudeP Z} * {Sin {AngleP Z}} end

fun {MakeFromRealImagP X Y} {Sqrt {Square X} + {Square Y}}#{Atan2 Y X} end
fun {MakeFromMagAngP M A} M#A end

% using the abstract type
Magnitude = MagnitudeP
Angle = AngleP
RealPart = RealPartP
ImagPart = ImagPartP
MakeFromRealImag = MakeFromRealImagP
MakeFromMagAng = MakeFromMagAngP

Z = 1.0#2.0
{Browse {MakeFromRealImag {RealPart Z} {ImagPart Z}}}
{Browse {MakeFromMagAng {Magnitude Z} {Angle Z}}}

fun {AddComplex Z1 Z2}
   {MakeFromRealImag
      {RealPart Z1} + {RealPart Z2}
      {ImagPart Z1} + {ImagPart Z2}}
end

fun {SubComplex Z1 Z2}
   {MakeFromRealImag
      {RealPart Z1} - {RealPart Z2}
      {ImagPart Z1} - {ImagPart Z2}}
end

fun {MulComplex Z1 Z2}
   {MakeFromMagAng
      {Magnitude Z1} * {Magnitude Z2}
      {Angle Z1} + {Angle Z2}}
end

fun {DivComplex Z1 Z2}
   {MakeFromMagAng
      {Magnitude Z1} / {Magnitude Z2}
      {Angle Z1} - {Angle Z2}}
end

% 2.4.2 Multiple Representations for Abstract Data - Tagged Data

fun {AttachTag TypeTag Contents} TypeTag(Contents) end

fun {TypeTag A}
   case A
   of rectangular(...) then rectangular
   [] polar(...) then polar
   else raise invalid('Invalid pattern match ' # A) end
   end
end

fun {Contents A}
   case A
   of rectangular(X) then X
   [] polar(X) then X
   else raise invalid('Invalid pattern match ' # A) end
   end
end

fun {IsRectangular A}
   case A
   of rectangular(...) then true
   else false
   end
end

fun {IsPolar A}
   case A
   of polar(...) then true
   else false
   end
end

% Rectangular
fun {MakeFromRealImagRectangular X Y}
   rectangular(X#Y)
end
fun {MakeFromMagAngRectangular M A}
   rectangular(M*{Cos A} # M*{Sin A})
end

fun {RealPartRectangular rectangular(X#_)} X end
fun {ImagPartRectangular rectangular(_#Y)} Y end

fun {MagnitudeRectangular Z}
   {Sqrt {Square {RealPartRectangular Z}} +
         {Square {ImagPartRectangular Z}}}
end
fun {AngleRectangular Z}
   {Atan2 {ImagPartRectangular Z} {RealPartRectangular Z}}
end

% Polar
fun {MakeFromRealImagPolar X Y}
   polar({Sqrt {Square X} + {Square Y}} # {Atan2 Y X})
end
fun {MakeFromMagAngPolar M A}
   polar(M A)
end

fun {MagnitudePolar polar(X#_)} X end
fun {AnglePolar polar(_#Y)} Y end

fun {RealPartPolar Z}
   {MagnitudePolar Z} * {Cos {AnglePolar Z}}
end
fun {ImagPartPolar Z}
   {MagnitudePolar Z} * {Sin {AnglePolar Z}}
end

% Generic selectors
fun {RealPartG A}
   case A
   of rectangular(_) then {RealPartRectangular A}
   [] polar(_) then {RealPartPolar A}
   else raise invalid('Invalid pattern match ' # A) end
   end
end
fun {ImagPartG A}
   case A
   of rectangular(_) then {ImagPartRectangular A}
   [] polar(_) then {ImagPartPolar A}
   else raise invalid('Invalid pattern match ' # A) end
   end
end

fun {MagnitudeG A}
   case A
   of rectangular(_) then {MagnitudeRectangular A}
   [] polar(_) then {MagnitudePolar A}
   else raise invalid('Invalid pattern match ' # A) end
   end
end
fun {AngleG A}
   case A
   of rectangular(_) then {AngleRectangular A}
   [] polar(_) then {AnglePolar A}
   else raise invalid('Invalid pattern match ' # A) end
   end
end

% Constructors for complex numbers
fun {MakeFromRealImagG X Y}
   {MakeFromRealImagRectangular X Y}
end
fun {MakeFromMagAngG M A}
   {MakeFromMagAngPolar M A}
end

% same as before
fun {AddComplexG Z1 Z2}
   {MakeFromRealImagG
      {RealPartG Z1} + {RealPartG Z2}
      {ImagPartG Z1} + {ImagPartG Z2}}
end

fun {SubComplexG Z1 Z2}
   {MakeFromRealImagG
      {RealPartG Z1} - {RealPartG Z2}
      {ImagPartG Z1} - {ImagPartG Z2}}
end

fun {MulComplexG Z1 Z2}
   {MakeFromMagAngG
      {MagnitudeG Z1} * {MagnitudeG Z2}
      {AngleG Z1} + {AngleG Z2}}
end

fun {DivComplexG Z1 Z2}
   {MakeFromMagAngG
      {MagnitudeG Z1} / {MagnitudeG Z2}
      {AngleG Z1} - {AngleG Z2}}
end

{Browse {AddComplexG {MakeFromRealImagG 3.0 4.0}
                     {MakeFromRealImagG 3.0 4.0}}}

% 2.4.3 Multiple Representations for Abstract Data - Data-Directed Programming and Additivity

RECTANGULAR =
   functor
   export
      makeFromRealImag : MakeFromRealImag
      makeFromMagAng   : MakeFromMagAng
      realPart         : RealPart
      imagPart         : ImagPart
      magnitude        : Magnitude
      angle            : Angle
      toString         : ToString
   define
      fun {MakeFromRealImag R I}
         rectangular(R#I)
      end
      fun {MakeFromMagAng M A}
         rectangular(M*{Cos A} # M*{Sin A})
      end
      fun {RealPart rectangular(X#_)} X end
      fun {ImagPart rectangular(_#Y)} Y end
      fun {Magnitude Z}
         {Sqrt {Square {RealPart Z}} +
               {Square {ImagPart Z}}}
      end
      fun {Angle Z}
         {Atan2 {ImagPart Z} {RealPart Z}}
      end
      fun {ToString Z}
         {StringToAtom {Append "r:" {Append {FloatToString {RealPart Z}} {Append " i:" {FloatToString {ImagPart Z}}}}}}
      end
   end
[Rectangular] = {Module.apply [RECTANGULAR]}

POLAR =
   functor
   export
      makeFromRealImag : MakeFromRealImag
      makeFromMagAng   : MakeFromMagAng
      realPart         : RealPart
      imagPart         : ImagPart
      magnitude        : Magnitude
      angle            : Angle
      toString         : ToString
   define
      fun {MakeFromRealImag R I}
         polar({Sqrt {Square R} + {Square I}} # {Atan2 Y I})
      end
      fun {MakeFromMagAng M A}
         polar(M A)
      end
      fun {Magnitude polar(M#_)} M end
      fun {Angle polar(_#A)} A end
      fun {RealPart Z}
         {Magnitude Z} * {Cos {Angle Z}}
      end
      fun {ImagPart Z}
         {Magnitude Z} * {Sin {Angle Z}}
      end
      fun {ToString Z}
         {StringToAtom {Append "m:" {Append {FloatToString {Magnitude Z}} {Append " a:" {FloatToString {Angle Z}}}}}}
      end
   end
[Polar] = {Module.apply [POLAR]}

COMPLEX =
   functor
   export
      numericType      : NumericType
      makeFromRealImag : MakeFromRealImag
      makeFromMagAng   : MakeFromMagAng
      add              : Add
      subtract         : Sub
      multiply         : Mul
      divide           : Div
      equal            : Equal
      toString         : ToString
   define
      NumericType = complex
      fun {ExtractFunctor F#_} F end
      fun {ExtractValue _#Z} Z end

      fun {MakeFromRealImag R I}
         Rectangular#{Rectangular.makeFromRealImag R I}
      end
      fun {MakeFromMagAng M A}
         Polar#{Polar.makeFromMagAng M A}
      end

      fun {Add F1#Z1 F2#Z2}
         {MakeFromRealImag
            {F1.realPart Z1} + {F2.realPart Z2}
            {F1.imagPart Z1} + {F2.imagPart Z2}}
      end
      fun {Sub F1#Z1 F2#Z2}
         {MakeFromRealImag
            {F1.realPart Z1} - {F2.realPart Z2}
            {F1.imagPart Z1} - {F2.imagPart Z2}}
      end
      fun {Mul F1#Z1 F2#Z2}
         {MakeFromMagAng
            {F1.magnitude Z1} * {F2.magnitude Z2}
            {F1.angle Z1} + {F2.angle Z2}}
      end
      fun {Div F1#Z1 F2#Z2}
         {MakeFromMagAng
            {F1.magnitude Z1} / {F2.magnitude Z2}
            {F1.angle Z1} - {F2.angle Z2}}
      end
      fun {Equal F1#Z1 F2#Z2}
         {F1.realPart Z1} == {F2.realPart Z2} andthen {F1.imagPart Z1} == {F2.imagPart Z2}
      end
      fun {ToString F#Z}
         {F.toString Z}
      end
   end
[Complex] = {Module.apply [COMPLEX]}

{Browse {Complex.toString {Complex.add {Complex.makeFromRealImag 3.0 4.0}
                          {Complex.makeFromRealImag 3.0 4.0}}}}

% Message Passing (aka OOP)
local
   class ComplexOO
      % abstract methods to be implemented by subclasses
      meth makeFromRealImag(R I ?$) raise abstract end end
      meth makeFromMagAng(M A ?$) raise abstract end end
      meth realPart(?$) raise abstract end end
      meth imagPart(?$) raise abstract end end
      meth magnitude(?$) raise abstract end end
      meth angle(?$) raise abstract end end
      meth toString(?$) raise abstract end end

      % base class methods
      meth add(Z ?$)
         R = {self realPart($)} + {Z realPart($)}
         I = {self imagPart($)} + {Z imagPart($)}
      in
         {self makeFromRealImag(R I $)}
      end
      meth subtract(Z ?$)
         R = {self realPart($)} - {Z realPart($)}
         I = {self imagPart($)} - {Z imagPart($)}
      in
         {self makeFromRealImag(R I $)}
      end
      meth multiply(Z ?$)
         M = {self magnitude($)} * {Z magnitude($)}
         A = {self angle($)} + {Z angle($)}
      in
         {self makeFromMagAng(M A $)}
      end
      meth divide(Z ?$)
         M = {self magnitude($)} / {Z magnitude($)}
         A = {self angle($)} - {Z angle($)}
      in
         {self makeFromMagAng(M A $)}
      end
      meth equal(Z ?$)
         {self realPart($)} == {Z realPart($)} andthen {self imagPart($)} == {Z imagPart($)}
      end
   end

   class RectangularOO from ComplexOO
      feat RealPart ImagPart
      meth init(R I)
         self.RealPart = R
         self.ImagPart = I
      end
      meth makeFromRealImag(R I ?$)
         {New RectangularOO init(R I)}
      end
      meth makeFromMagAng(M A ?$)
         {New RectangularOO init(M*{Cos A} M*{Sin A})}
      end
      meth realPart(?$) self.RealPart end
      meth imagPart(?$) self.ImagPart end
      meth magnitude(?$)
         {Sqrt {Square self.RealPart} +
               {Square self.ImagPart}}
      end
      meth angle(?$)
         {Atan2 self.ImagPart self.RealPart}
      end
      meth toString(?$)
         {StringToAtom {Append "r:" {Append {FloatToString self.RealPart} {Append " i:" {FloatToString self.ImagPart}}}}}
      end
   end

   class PolarOO from ComplexOO
      feat Magnitude Angle
      meth init(M A)
         self.Magnitude = M
         self.Angle = A
      end
      meth makeFromRealImag(R I ?$)
         {New PolarOO init({Sqrt {Square R} + {Square I}} {Atan2 I R})}
      end
      meth makeFromMagAng(M A ?$)
         {New PolarOO init(M A)}
      end
      meth magnitude(?$) self.Magnitude end
      meth angle(?$) self.Angle end
      meth realPart(?$)
         self.Magnitude * {Cos self.Angle}
      end
      meth imagPart(?$)
         self.Magnitude * {Sin self.Angle}
      end
      meth toString(?$)
         {StringToAtom {Append "m:" {Append {FloatToString self.Magnitude} {Append " a:" {FloatToString self.Angle}}}}}
      end
   end
in
   RecX = {New RectangularOO init(3.0 4.0)}
   {Browse {RecX realPart($)}#{RecX imagPart($)}}
   {Browse {RecX magnitude($)}#{RecX angle($)}}

   PolX = {New PolarOO init({RecX magnitude($)} {RecX angle($)})}
   {Browse {PolX realPart($)}#{PolX imagPart($)}}
   {Browse {PolX magnitude($)}#{PolX angle($)}}

   AddX = {PolX add(RecX $)}
   {Browse {AddX realPart($)}#{AddX imagPart($)}}
   {Browse {AddX magnitude($)}#{AddX angle($)}}
end

% footnote
{Browse {FoldL [1 2 3 4] Number.'+' 0}}

% 2.5.1 Systems with Generic Operations - Generic Arithmetic Operations

% functor solution
OZINTEGER =
   functor
   export
      numericType : NumericType
      make        : Make
      add         : Add
      subtract    : Sub
      multiply    : Mul
      divide      : Div
      equal       : Equal
      toString    : ToString
   define
      NumericType = ozinteger
      fun {Make X} X end
      fun {Add X Y} X + Y end
      fun {Sub X Y} X - Y end
      fun {Mul X Y} X * Y end
      fun {Div X Y} X div Y end
      fun {Equal X Y} X == Y end
      fun {ToString X} {StringToAtom {IntToString X}} end
   end
[OzInteger] = {Module.apply [OZINTEGER]}

OZFLOAT =
   functor
   export
      numericType : NumericType
      make        : Make
      add         : Add
      subtract    : Sub
      multiply    : Mul
      divide      : Div
      equal       : Equal
      toString    : ToString
   define
      NumericType = ozfloat
      fun {Make X} X end
      fun {Add X Y} X + Y end
      fun {Sub X Y} X - Y end
      fun {Mul X Y} X * Y end
      fun {Div X Y} X / Y end
      fun {Equal X Y} X == Y end
      fun {ToString X} {StringToAtom {FloatToString X}} end
   end
[OzFloat] = {Module.apply [OZFLOAT]}

local
   NUMERIC =
      functor
      export
         make     : Make
         add      : Add
         subtract : Sub
         multiply : Mul
         divide   : Div
         equal    : Equal
         toString : ToString
      define
         fun {Make F X} F#X end
         fun {Add F1#X F2#Y} F1#{F1.add X Y} end
         fun {Sub F1#X F2#Y} F1#{F1.subtract X Y} end
         fun {Mul F1#X F2#Y} F1#{F1.multiply X Y} end
         fun {Div F1#X F2#Y} F1#{F1.divide X Y} end
         fun {Equal F1#X F2#Y} {F1.equal X Y} end
         fun {ToString F#X} {F.toString X} end
      end
   [Numeric] = {Module.apply [NUMERIC]}

   NR1 = {Numeric.make Rational {Rational.make 3 4}}
   NC1 = {Numeric.make Complex {Complex.makeFromRealImag 3.0 4.0}}
   NI1 = {Numeric.make OzInteger {OzInteger.make 3}}
   NF1 = {Numeric.make OzFloat {OzFloat.make 3.0}}

   NR2 = {Numeric.make Rational {Rational.make 5 6}}
   NC2 = {Numeric.make Complex {Complex.makeFromRealImag 5.0 6.0}}
   NI2 = {Numeric.make OzInteger {OzInteger.make 5}}
   NF2 = {Numeric.make OzFloat {OzFloat.make 5.0}}
in
   {Browse {Numeric.toString NR1}#{Numeric.toString NR2}}
   {Browse {Numeric.toString NC1}#{Numeric.toString NC2}}
   {Browse {Numeric.toString NI1}#{Numeric.toString NI2}}
   {Browse {Numeric.toString NF1}#{Numeric.toString NF2}}

   {Browse {Numeric.toString {Numeric.add NR1 NR2}}}
   {Browse {Numeric.toString {Numeric.add NC1 NC2}}}
   {Browse {Numeric.toString {Numeric.add NI1 NI2}}}
   {Browse {Numeric.toString {Numeric.add NF1 NF2}}}
end

% Object Solution
local
   class NumericOO
      % abstract methods to be implemented by subclasses
      meth add(X Y ?$) raise abstract end end
      meth subtract(X Y ?$) raise abstract end end
      meth multiply(X Y ?$) raise abstract end end
      meth divide(X Y ?$) raise abstract end end
      meth equal(X Y ?$) raise abstract end end
      meth toString(X ?$) raise abstract end end
   end

   class ComplexOO from NumericOO
      % abstract methods to be implemented by subclasses
      meth makeFromRealImag(R I ?$) raise abstract end end
      meth makeFromMagAng(M A ?$) raise abstract end end
      meth realPart(?$) raise abstract end end
      meth imagPart(?$) raise abstract end end
      meth magnitude(?$) raise abstract end end
      meth angle(?$) raise abstract end end

      % base class methods
      meth add(Z ?$)
         R = {self realPart($)} + {Z realPart($)}
         I = {self imagPart($)} + {Z imagPart($)}
      in
         {self makeFromRealImag(R I $)}
      end
      meth subtract(Z ?$)
         R = {self realPart($)} - {Z realPart($)}
         I = {self imagPart($)} - {Z imagPart($)}
      in
         {self makeFromRealImag(R I $)}
      end
      meth multiply(Z ?$)
         M = {self magnitude($)} * {Z magnitude($)}
         A = {self angle($)} + {Z angle($)}
      in
         {self makeFromMagAng(M A $)}
      end
      meth divide(Z ?$)
         M = {self magnitude($)} / {Z magnitude($)}
         A = {self angle($)} - {Z angle($)}
      in
         {self makeFromMagAng(M A $)}
      end
      meth equal(Z ?$)
         {self realPart($)} == {Z realPart($)} andthen {self imagPart($)} == {Z imagPart($)}
      end
   end

   class RectangularOO from ComplexOO
      feat RealPart ImagPart
      meth init(R I)
         self.RealPart = R
         self.ImagPart = I
      end
      meth makeFromRealImag(R I ?$)
         {New RectangularOO init(R I)}
      end
      meth makeFromMagAng(M A ?$)
         {New RectangularOO init(M*{Cos A} M*{Sin A})}
      end
      meth realPart(?$) self.RealPart end
      meth imagPart(?$) self.ImagPart end
      meth magnitude(?$)
         {Sqrt {Square self.RealPart} +
               {Square self.ImagPart}}
      end
      meth angle(?$)
         {Atan2 self.ImagPart self.RealPart}
      end
      meth toString(?$)
         {StringToAtom {Append "r:" {Append {FloatToString self.RealPart} {Append " i:" {FloatToString self.ImagPart}}}}}
      end
   end

   class PolarOO from ComplexOO
      feat Magnitude Angle
      meth init(M A)
         self.Magnitude = M
         self.Angle = A
      end
      meth makeFromRealImag(R I ?$)
         {New PolarOO init({Sqrt {Square R} + {Square I}} {Atan2 I R})}
      end
      meth makeFromMagAng(M A ?$)
         {New PolarOO init(M A)}
      end
      meth magnitude(?$) self.Magnitude end
      meth angle(?$) self.Angle end
      meth realPart(?$)
         self.Magnitude * {Cos self.Angle}
      end
      meth imagPart(?$)
         self.Magnitude * {Sin self.Angle}
      end
      meth toString(?$)
         {StringToAtom {Append "m:" {Append {FloatToString self.Magnitude} {Append " a:" {FloatToString self.Angle}}}}}
      end
   end

   class OzIntegerOO from NumericOO
      feat val
      meth init(X) self.val = X end
      meth add(Y ?$) {New OzIntegerOO init(self.val + Y.val)} end
      meth subtract(Y ?$) {New OzIntegerOO init(self.val - Y.val)} end
      meth multiply(Y ?$) {New OzIntegerOO init(self.val * Y.val)} end
      meth divide(Y ?$) {New OzIntegerOO init(self.val div Y.val)} end
      meth equal(Y $) self.val == Y.val end
      meth toString(?$) {StringToAtom {IntToString self.val}} end
   end

   class OzFloatOO from NumericOO
      feat val
      meth init(X) self.val = X end
      meth add(Y ?$) {New OzFloatOO init(self.val + Y.val)} end
      meth subtract(Y ?$) {New OzFloatOO init(self.val - Y.val)} end
      meth multiply(Y ?$) {New OzFloatOO init(self.val * Y.val)} end
      meth divide(Y ?$) {New OzFloatOO init(self.val div Y.val)} end
      meth equal(Y $) self.val == Y.val end
      meth toString(?$) {StringToAtom {FloatToString self.val}} end
   end

   NR1 = {New RationalOO init(3 4)}
   NC1 = {New RectangularOO init(3.0 4.0)}
   NI1 = {New OzIntegerOO init(3)}
   NF1 = {New OzFloatOO init(3.0)}

   NR2 = {New RationalOO init(5 6)}
   NC2 = {New RectangularOO init(5.0 6.0)}
   NI2 = {New OzIntegerOO init(5)}
   NF2 = {New OzFloatOO init(5.0)}
in
   {Browse {NR1 toString($)}#{NR2 toString($)}}
   {Browse {NC1 toString($)}#{NC2 toString($)}}
   {Browse {NI1 toString($)}#{NI2 toString($)}}
   {Browse {NF1 toString($)}#{NF2 toString($)}}

   {Browse {{NR1 add(NR2 $)} toString($)}}
   {Browse {{NC1 add(NC2 $)} toString($)}}
   {Browse {{NI1 add(NI2 $)} toString($)}}
   {Browse {{NF1 add(NF2 $)} toString($)}}
end

% 2.5.2 Systems with Generic Operations - Combining Data of Different Types

local
   NUMERIC =
      functor
      export
         make     : Make
         add      : Add
         subtract : Sub
         multiply : Mul
         divide   : Div
         equal    : Equal
         toString : ToString
      define
         fun {Integer2Rational X}
            {Rational.make X 1}
         end
         fun {Rational2Float X}
            {IntToFloat {Rational.numer X}} / {IntToFloat {Rational.denom X}}
         end
         fun {Float2Complex X}
            {Complex.makeFromRealImag X 0.0}
         end

         D = {NewDictionary}
         {Dictionary.put D ozinteger2rational [Integer2Rational]}
         {Dictionary.put D ozinteger2ozfloat  [Rational2Float Integer2Rational]}
         {Dictionary.put D ozinteger2complex  [Float2Complex Rational2Float Integer2Rational]}
         {Dictionary.put D rational2ozfloat   [Rational2Float]}
         {Dictionary.put D rational2complex   [Float2Complex Rational2Float]}
         {Dictionary.put D ozfloat2complex    [Float2Complex]}

         fun {Coerce F1#X F2#Y}
            if F1 == F2 then
               F1#X#Y
            else
               local
                  T1 = {AtomToString F1.numericType}
                  T2 = {AtomToString F2.numericType}
                  X2Y = {StringToAtom {Append T1 {Append "2" T2}}}
                  Y2X = {StringToAtom {Append T2 {Append "2" T1}}}
               in
                  if {Dictionary.member D X2Y} then
                     F2#{Accumulate {Dictionary.get D X2Y} fun {$ F N} {F N} end X}#Y
                  elseif {Dictionary.member D Y2X} then
                     F1#X#{Accumulate {Dictionary.get D Y2X} fun {$ F N} {F N} end Y}
                  else
                     raise coerce({StringToAtom T1} {StringToAtom T2}) end
                  end
               end
            end
         end

         fun {Make F X} F#X end
         fun {Add X Y} F#A#B = {Coerce X Y} in F#{F.add A B} end
         fun {Sub X Y} F#A#B = {Coerce X Y} in F#{F.subtract A B} end
         fun {Mul X Y} F#A#B = {Coerce X Y} in F#{F.multiply A B} end
         fun {Div X Y} F#A#B = {Coerce X Y} in F#{F.divide A B} end
         fun {Equal X Y} F#A#B = {Coerce X Y} in F#{F.equal A B} end
         fun {ToString F#X} {F.toString X} end
      end
   [Numeric] = {Module.apply [NUMERIC]}

   NR1 = {Numeric.make Rational {Rational.make 3 4}}
   NC1 = {Numeric.make Complex {Complex.makeFromRealImag 3.0 4.0}}
   NI1 = {Numeric.make OzInteger {OzInteger.make 3}}
   NF1 = {Numeric.make OzFloat {OzFloat.make 3.0}}

   NR2 = {Numeric.make Rational {Rational.make 5 6}}
   NC2 = {Numeric.make Complex {Complex.makeFromRealImag 5.0 6.0}}
   NI2 = {Numeric.make OzInteger {OzInteger.make 5}}
   NF2 = {Numeric.make OzFloat {OzFloat.make 5.0}}
in
   {Browse {Numeric.toString {Numeric.add NI1 NI2}}}
   {Browse {Numeric.toString {Numeric.add NI1 NR2}}}
   {Browse {Numeric.toString {Numeric.add NI1 NF2}}}
   {Browse {Numeric.toString {Numeric.add NI1 NC2}}}

   {Browse {Numeric.toString {Numeric.add NR1 NI2}}}
   {Browse {Numeric.toString {Numeric.add NR1 NR2}}}
   {Browse {Numeric.toString {Numeric.add NR1 NF2}}}
   {Browse {Numeric.toString {Numeric.add NR1 NC2}}}

   {Browse {Numeric.toString {Numeric.add NF1 NI2}}}
   {Browse {Numeric.toString {Numeric.add NF1 NR2}}}
   {Browse {Numeric.toString {Numeric.add NF1 NF2}}}
   {Browse {Numeric.toString {Numeric.add NF1 NC2}}}

   {Browse {Numeric.toString {Numeric.add NC1 NI2}}}
   {Browse {Numeric.toString {Numeric.add NC1 NR2}}}
   {Browse {Numeric.toString {Numeric.add NC1 NF2}}}
   {Browse {Numeric.toString {Numeric.add NC1 NC2}}}
end

% 2.5.3 Systems with Generic Operations - Example: Symbolic Algebra

% To Be Done.

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