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