看了SICP第三章的约束器的例子,用Scheme实现了一遍,现在用Python以OO的方式再实现了一遍:
9C=5(F-32)
感觉上因为命令式用的比较多,还是OO方式比FP好理解。
class adder(object):
def __init__(self, a1, a2, s):
self.a1 = a1.connect(self)
self.a2 = a2.connect(self)
self.s = s.connect(self)
def process_new_value(self):
if self.a1.has_value() and self.a2.has_value():
self.s.set_value(self.a1.value() + self.a2.value(), self)
elif self.a1.has_value() and self.s.has_value():
self.a2.set_value(self.s.value() - self.a1.value(), self)
elif self.a2.has_value() and self.s.has_value():
self.a1.set_value(self.s.value() - self.a2.value(), self)
def process_forget_value(self):
self.a1.forget_value(self)
self.a2.forget_value(self)
self.s.forget_value(self)
self.process_new_value()
class multiplier(object):
def __init__(self, a1, a2, p):
self.a1 = a1.connect(self)
self.a2 = a2.connect(self)
self.p = p.connect(self)
def process_new_value(self):
if (self.a1.has_value() and self.a1.value() == 0) or (self.a2.has_value() and self.a2.value() == 0):
self.p.set_value(0, self)
if self.a1.has_value() and self.a2.has_value():
self.p.set_value(self.a1.value() * self.a2.value(), self)
elif self.a1.has_value() and self.p.has_value():
self.a2.set_value(self.p.value() / self.a1.value(), self)
elif self.a2.has_value() and self.p.has_value():
self.a1.set_value(self.p.value() / self.a2.value(), self)
def process_forget_value(self):
self.a1.forget_value(self)
self.a2.forget_value(self)
self.p.forget_value(self)
self.process_new_value()
class constant(object):
def __init__(self, v, connector):
connector.connect(self)
connector.set_value(v, self)
def process_new_value(self): pass
def process_forget_value(self): pass
class connector(object):
def __init__(self):
self.myValue = None
self.lastSetter = None
self.constraints = set()
def connect(self, constraint):
self.constraints.add(constraint)
return self
def has_value(self):
return self.myValue != None
def value(self):
return self.myValue
def set_value(self, v, setter):
if self.myValue is None:
self.myValue, self.lastSetter = v, setter
map(lambda x: x.process_new_value(),
[each for each in self.constraints if each != setter])
elif self.myValue != v:
raise Exception, "Input confilicat!"
def forget_value(self, cleaner):
if self.lastSetter == cleaner:
self.lastSetter = self.myValue = None
map(lambda x: x.process_forget_value(),
[each for each in self.constraints if each != cleaner])
class probe(object):
def __init__(self, name, connector):
self.name = name
self.connector = connector
connector.connect(self)
def output(self, value):
if value is not None:
print "Probe : %s = %d" % (self.name, value)
else:
print "Probe : %s = ?" % self.name
def process_new_value(self):
self.output(self.connector.value())
def process_forget_value(self):
self.output(None)
def celsius_fahreneit_converter(c, f):
u, v, w, x, y = connector(), connector(), connector(), connector(), connector()
multiplier(c, w, u)
multiplier(v, x, u)
adder(v, y, f)
constant(9, w)
constant(5, x)
constant(32, y)
def main():
c, f = connector(), connector()
celsius_fahreneit_converter(c, f)
probe("Celsius temp", c)
probe("Fahrenheit temp", f)
c.set_value(25, 'user')
c.forget_value('user')
f.set_value(212, 'user')
if __name__ == '__main__':
main()