| code |
package mylib;
object constr {
class Quantity{
private var value:Option[double]=None;
private var contraints:List[Contraint]=List();
private var informant:Contraint=NoContraint;
def getValue:Option[double]=value;
def setValue(v:double,setter:Contraint):unit=value match{
case Some(v1)=>if(v!=v1) error("Error!Contradiction:"+v+" and " +v1);
case None=>{
informant=setter;
value=Some(v);
for(val c<-contraints;c!=informant)
c.newValue;
}
}
def setValue(v:double):unit=setValue(v,NoContraint);
def forgetValue(retractor:Contraint):unit={
if(retractor==informant)
{
value=None;
for(val c<-contraints;c!=informant)c.dropValue;
}
}
def forgetValue:unit=forgetValue(NoContraint);
def connect(c:Contraint):unit={
contraints=c::contraints;
value match{
case Some(_)=>c.newValue
case None=>}
}
}
trait Option[+a];
case class Some[+a](value:a)extends Option[a];
case object None extends Option[Nothing];
abstract class Contraint{
def newValue:unit;
def dropValue:unit;
}
case class Adder(al:Quantity,a2:Quantity,sum:Quantity)extends Contraint{
def newValue:unit={Triple(al.getValue,a2.getValue,sum.getValue) match{
case Triple(Some(x1),Some(x2),_)=>sum.setValue(x1+x2,this);
case Triple(Some(x1),_,Some(r))=>a2.setValue(r-x1,this);
case Triple(_,Some(x2),Some(r))=>al.setValue(r-x2,this);
case _=>}}
def dropValue:unit={
al.forgetValue(this);
a2.forgetValue(this);
sum.forgetValue(this);
}
al connect this;
a2 connect this;
sum connect this;
}
case class Constant(q:Quantity,v:double)extends Contraint{
def newValue:unit=error("Constant.newValue");
def dropValue:unit=error("Constant.dropValue");
q connect this;
q.setValue(v,this);
}
case class NoContraint extends Contraint{
def newValue:unit=error("Constant.newValue");
def dropValue:unit=error("Constant.dropValue");
}
case class Multiplier(al:Quantity,a2:Quantity,sum:Quantity) extends Contraint{
def newValue:unit={Triple(al.getValue,a2.getValue,sum.getValue)match{
case Triple(Some(x1),Some(x2),_)=>sum.setValue(x1*x2,this)
case Triple(Some(x1),_,Some(r))=>a2.setValue(r/x1,this)
case Triple(_,Some(x2),Some(r))=>al.setValue(r/x2,this)
case Triple(Some(0),_,_)=>al.setValue(0,this)
case Triple(_,Some(0),_)=>al.setValue(0,this)
case _=>}
}
def dropValue:unit={
al.forgetValue(this);
a2.forgetValue(this);
sum.forgetValue(this);
}
}
case class Probe(name:String,q:Quantity) extends Contraint{
def newValue:unit=printProbe(q.getValue);
def dropValue:unit=printProbe(None);
private def printProbe(v:Option[double]):unit={
val vstr=v match{
case Some(x)=>x.toString();
case None=>"?";
}
Console.println("Probe:"+name+"="+vstr);
}
}
def CFconverter(c:Quantity,f:Quantity)={
val u,v,w,x,y=new Quantity;
Constant(x,9);
Multiplier(c,x,u);
Constant(w,-32);
Adder(f,w,v)
Constant(y,5);
Multiplier(v,y,u);
}
def main(args : Array[String]):Unit = {
val C,F=new Quantity;
CFconverter(C,F);
Probe("Celsius temp",C);
Probe("Fahrenheit temp",F);
C setValue 25;
}
}
|