ML "Objects"


The code below is an ML version of the Simula code in the reader. What's the point of the ML rendition?

1. For this "motivating example," ordinary non-object-oriented language is just as good, if not better than the Simula version. (The ML, closure version hides the instance variables, permitting access only through the "methods".

2. Raises basic question:
Is OOP:
a fundamental idea?
or a set of related programming techniques?
(* ----------------- Point Class from pg 130  ---------------- *)

fun New_Point(xval,yval:real) =
   let val x = (ref xval) and y = (ref yval) in
       {
       x_meth  = fn () => !x,
       y_meth  = fn () => !y,
       eq_meth = fn (p as {x_meth=xm, y_meth=ym, eq_meth=em, dis_meth=dm}) =>
                     abs(!x - xm()) + abs(!y - ym()) < 0.00001,
       dis_meth =fn (p as {x_meth=xm, y_meth=ym, eq_meth=em, dis_meth=dm}) =>
                     sqrt( (!x - xm())*(!x - xm()) + (!y - ym())*(!y - ym()) )
       }
   end;

(*  -- create two points --   *)

val orig = New_Point(0.0,0.0);
val p = New_Point(1.0,1.0);

(* -- compare for equality -- *)

let val {x_meth=xm, y_meth=ym, eq_meth=em, dis_meth=dm} = orig in em(orig) end;
let val {x_meth=xm, y_meth=ym, eq_meth=em, dis_meth=dm} = orig in em(p) end;

(*  -- compute distance --   *)

let val {x_meth=xm, y_meth=ym, eq_meth=em, dis_meth=dm} = orig in dm(p) end;
let val {x_meth=xm, y_meth=ym, eq_meth=em, dis_meth=dm} = p    in dm(orig) end;

(* ----------------- Line Class -------------------------------- *)
exception Parallel;

fun New_Line(aval,bval,cval:real) =
   let val d = sqrt(aval*aval + bval*bval) (* leave div by 0 check to ML *)
       val a = (ref (aval/d)) and b = (ref (bval/d)) and c = (ref (cval/d)) in
       {
       a_meth  = fn () => !a,
       b_meth  = fn () => !b,
       c_meth  = fn () => !c,
       p_meth = fn (l as {a_meth=am, b_meth=bm, c_meth=cm, p_meth=pm, m_meth=mm}) =>
                     abs(!a * bm() - !b * am()) < 0.00001,
       m_meth = fn (l as {a_meth=am, b_meth=bm, c_meth=cm, p_meth=pm, m_meth=mm}) =>
                if abs(!a * bm() - !b * am()) < 0.00001 then raise Parallel
                   else  let val t = 1.0/(am() * !b - bm() * !a)
                         in  New_Point(~t * (cm()* !b - bm() * !c),
                                        t * (cm()* !a - am() * !c))
                         end
       }
   end;

(*  -- create two lines --   *)

val l1 = New_Line(1.0,1.0,0.0);
val l2 = New_Line(1.0,2.0,1.0);

(*  -- check if parallel  -- *)

let val {a_meth=am, b_meth=bm, c_meth=cm, p_meth=pm, m_meth=mm} = l1 in pm(l1) end;
let val {a_meth=am, b_meth=bm, c_meth=cm, p_meth=pm, m_meth=mm} = l1 in pm(l2) end;

(*  -- compute intersection -- *)

val inter = 
  let val {a_meth=am, b_meth=bm, c_meth=cm, p_meth=pm, m_meth=mm} = l1 
  in mm(l2)
  end;

(* -- get x,y coords of point -- *)

let val {x_meth=xm, y_meth=ym, eq_meth=em, dis_meth=dm} = inter in xm() end;
let val {x_meth=xm, y_meth=ym, eq_meth=em, dis_meth=dm} = inter in ym() end;


Kathleen Fisher / kfisher@cs.stanford.edu