from mext.reaction import *
@atomic
def init(container):
a = A()
a.Id = "a"
container.add(a)
b = A()
b.Id = "b"
container.add(b)
b.previous = a
c = A()
c.Id = "c"
container.add(c)
c.previous = b
class A(Component):
attrs (
Id = "",
size = 3,
space = 5,
previous = None,
left = -1,
right = 999,
)
@maintain
def SetLeft(self):
value = 0
if self.previous:
value = self.previous.right + self.space
self.left = value
@maintain
def SetRight(self):
self.right = self.left + self.size
def __repr__(self):
value = "%r: [%r,%r]" % (self.Id, self.left, self.right)
if self.previous:
value += " p=%r" % (self.previous.Id)
return value
cont = set()
init(cont)
for a in cont:
print a
'a': [0,3]
'b': [8,11] p='a'
'c': [16,19] p='b'
'a': [0,3]
'b': [8,3] p='a'
'c': [8,11] p='b'
'a': [0,3]
'b': [8,3] p='a'
'c': [8,3] p='b'
The problem is caused by special status of initialization and how it
plays with circularity / wrong order detection. Reimplementing it is
on top of my list for Reaction, but I can't tell you when will I get
to work on it again. Maybe later this month, maybe in October.
http://code.google.com/p/trellis-fork/issues/detail?id=5
Anyway, this problem only matters for @maintain rules and I didn't
write the new docs yet, but one of the things I wanted to explain
there is that for cleaner, easy-to-understand and safe code one should
avoid @maintain as much as possible, whenever possible, opt for
readonly rules (@compute and @track). It's also true for Trellis, but
I specifically worked to make Reaction guide to that kind of design.
For your example that would mean the following changes:
* first of all, replace SetRight w/ a compute rule:
class A(Component):
attrs (
Id = "",
size = 3,
space = 5,
previous = None,
left = -1,
)
@maintain
def SetLeft(self):
value = 0
if self.previous:
value = self.previous.right + self.space
self.left = value
@compute
def right(self):
return self.left + self.size
def __repr__(self):
value = "%r: [%r,%r]" % (self.Id, self.left, self.right)
if self.previous:
value += " p=%r" % (self.previous.Id)
return value
If you try that edit, you'll see that the problem is gone.
* SetLeft should be replaced w/ a compute rule as well, but it might
not be obvious how to do it -- it should be settable. That's why
reaction.compute has a (write=) arg
class A(Component):
attrs (
Id = "",
size = 3,
space = 5,
previous = None,
_left = 0,
)
@compute(write_to='_left')
def left(self):
if self.previous:
return self.previous.right + self.space
else:
return self._left
@compute
def right(self):
return self.left + self.size
def __repr__(self):
value = "%r: [%r,%r]" % (self.Id, self.left, self.right)
if self.previous:
value += " p=%r" % (self.previous.Id)
return value
One could go further and make sure .left is not settable when
.previous is not None or do the Coherence-like thing and change
.previous.left in such cases, but I'll stop here.
Anyway, the problem is a known bug and (unless I'm really confused)
inherited from Trellis. I do know how to fix it (it will go away
magically after init system is rewritten in a certain way), but you
still shouldn't be using @maintains in that way.
-Sergey
2009/8/26 Edwin <edwind...@gmail.com>:
--
Best Regards,
Sergey Schetinin
http://s3bk.com/ -- S3 Backup
http://word-to-html.com/ -- Word to HTML Converter
def __init__(self):
self.SetRight
self.SetLeft
to A -- I believe the correct result you get w/ Trellis is just luck
-- this __init__ will force the initial incorrect order and unless
Trellis does handle that it will have the same problem.
2009/9/10 Edwin <edwind...@gmail.com>:
2009/9/10 Sergey Schetinin <mal...@gmail.com>:
I was wrong when saying that it would fail in the same way w/ Trellis,
but it is actually init-related. There are a few init-related issues
w/ Trellis and some of them fixed in Reaction, some of them not (you
can find them in tests/ dir).
A few more things, for some reason copy-pasting code from your emails
looses all the indentation and text-version of them is kinda garbled,
please try to make sure you send messages in text-format so that code
indentation is OK.
Also, you might be interested in a more idiomatic version of your code:
from __future__ import with_statement
from mext.reaction import *
class A(Component):
attrs(
Id = "",
size = 3,
space = 5,
previous = None,
left = -1,
right = 999,
)
@maintain
def SetLeft(self):
value = 0
if self.previous:
value = self.previous.right + self.space
self.left = value
@maintain
def SetRight(self):
self.right = self.left + self.size
def __repr__(self):
value = "%r: [%r,%r]" % (self.Id, self.left, self.right)
if self.previous:
value += " p=%r" % (self.previous.Id)
return value
with ctrl.new_txn():
a = A(Id='a')
b = A(Id='b', previous=a)
c = A(Id='c')
c.previous = b
#print '---'
#print get_cell(a, 'right') in list(get_cell(b, 'SetLeft').iter_subjects())
#print get_cell(b, 'SetLeft') in list(get_cell(a, 'right').iter_listeners())
print a
print b
print c
#print list(get_cell(b, 'SetLeft').iter_subjects())
#print list(get_cell(c, 'SetRight').iter_subjects())
2009/9/10 Sergey Schetinin <mal...@gmail.com>: