Last active
August 29, 2015 14:02
-
-
Save debetimi/96d080684c5bd7906866 to your computer and use it in GitHub Desktop.
Reactive Programming Baby Steps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import namedtuple | |
enum = namedtuple('Operations', ['add', 'subtract', 'multiply', 'divide']) | |
operations = enum(add='+', subtract="-", multiply="*", divide="/") | |
class Relation: | |
def __init__(self, a, b, op): | |
self.a = a | |
self.b = b | |
self.op = op | |
def can_calculate(self, var): | |
if self.has_dependency(var): | |
return False; | |
return self.a.has_value(var) and self.b.has_value(var) | |
def value(self): | |
if self.op == operations.add: | |
return self.a.get() + self.b.get() | |
elif self.op == operations.subtract: | |
return self.a.get() - self.b.get() | |
def unlock(self): | |
if self.a.locked: | |
self.a.unlock() | |
if self.b.locked: | |
self.b.unlock() | |
def has_dependency(self, other): | |
return self.a == other or self.b == other | |
class Var: | |
def __init__(self, value=None): | |
self.value = value | |
self.relationships = [] | |
self.locked = value != None | |
self.is_const = value != None | |
def get(self, dependency=None): | |
if self.is_const: | |
return self.value | |
for relation in self.relationships: | |
if relation.has_dependency(dependency): | |
continue | |
if relation.can_calculate(self): | |
self.lock() | |
return relation.value() | |
return None | |
def add_relation(self, relation): | |
self.relationships.append(relation) | |
def set(self, value): | |
if self.locked: | |
raise Exception("Value set by dependecies, must free dependent variable") | |
self.value = value | |
self.is_const = True | |
def has_value(self, dependency=None): | |
return self.get(dependency) is not None | |
def lock(self): | |
self.locked = True | |
def unlock(self): | |
if self.locked: | |
self.locked = False | |
self.unlock_relationships() | |
def free(self): | |
if not self.is_const: | |
print "FREEING A NON CONSTANT IS A NO-OP" | |
return | |
self.unlock() | |
self.is_const = False | |
self.value = None | |
def unlock_relationships(self): | |
for relation in self.relationships: | |
relation.unlock() | |
def __add__(self, that): | |
e = Var() | |
if Var.is_numeric(that): | |
constant = Var(that) | |
e.add_relation(Relation(self, constant, operations.add)) | |
self.add_relation(Relation(e, constant, operations.subtract)) | |
elif isinstance(that, Var): | |
e.add_relation(Relation(self, that, operations.add)) | |
self.add_relation(Relation(e, that, operations.subtract)) | |
that.add_relation(Relation(e, self, operations.subtract)) | |
return e | |
def __sub__(self, that): | |
e = Var() | |
e.add_relation(Relation(self, that, operations.subtract)) | |
self.add_relation(Relation(e, that, operations.add)) | |
that.add_relation(Relation(self, e, operations.subtract)) | |
return e | |
def __str__(self): | |
return str(self.get()) | |
def __repr__(self): | |
return self.__str__() | |
@staticmethod | |
def is_numeric(x): | |
return isinstance(x, int) or isinstance(x, float) or isinstance(x, long) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
In [1]: from var import * | |
In [2]: a = Var() | |
In [3]: b = Var() | |
In [4]: c = a + b | |
In [5]: c | |
Out[5]: None | |
In [6]: a | |
Out[6]: None | |
In [7]: b | |
Out[7]: None | |
In [8]: a.set(1) | |
In [9]: c.set(1) | |
In [10]: b | |
Out[10]: 0 | |
In [11]: a | |
Out[11]: 1 | |
In [12]: c | |
Out[12]: 1 | |
In [13]: b.set(3) | |
--------------------------------------------------------------------------- | |
Exception Traceback (most recent call last) | |
/home/tokah/Desktop/<ipython-input-13-c0c349896a0d> in <module>() | |
----> 1 b.set(3) | |
/home/tokah/Desktop/var.py in set(self, value) | |
54 def set(self, value): | |
55 if self.locked: | |
---> 56 raise Exception("Value set by dependecies, must free dependent variable") | |
57 self.value = value | |
58 self.is_const = True | |
Exception: Value set by dependecies, must free dependent variable | |
In [14]: a.free() | |
In [15]: a | |
Out[15]: None | |
In [16]: b | |
Out[16]: None | |
In [17]: c | |
Out[17]: 1 | |
In [18]: b.set(3) | |
In [19]: a | |
Out[19]: -2 | |
In [20]: b | |
Out[20]: 3 | |
In [21]: c | |
Out[21]: 1 | |
In [22]: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment