, "and=" , "or=" , "&=" , "|="
, ":-"
, "="
- , "majority=" , "set=" , "bag="
+ , "majority=" , "mean="
+ , "set=" , "bag="
, ":="
, "dict="
]
class majority_equals(BAggregator):
def fold(self):
- [(k,_)] = self.most_common(1)
- return k
+ [(k,c)] = self.most_common(1)
+ if c > 0:
+ return k
+
+class mean_equals(BAggregator):
+ def fold(self):
+ # TODO: support negative multiplicity or throw an error
+ s = [k*m for k, m in self.iteritems() if m > 0]
+ if len(s):
+ n = sum(m for _, m in self.iteritems() if m > 0)
+ return reduce(operator.add, s) / n
class max_equals(BAggregator):
def fold(self):
class set_equals(BAggregator):
def fold(self):
+ from stdlib import todynalist
s = {x for x, m in self.iteritems() if m > 0}
if len(s):
- return s
+ return todynalist(s)
class bag_equals(BAggregator):
def fold(self):
- return Counter(self)
+ from stdlib import todynalist
+ return todynalist(Counter(self).elements())
# map names to functions
'majority=': majority_equals,
'set=': set_equals,
'bag=': bag_equals,
+ 'mean=': mean_equals,
}
def aggregator(name):
except ValueError:
print 'Please specify an integer. Type `help retract_rule` to read more.'
else:
- if self.interp.retract_rule(idx) is None:
+ changes = self.interp.retract_rule(idx)
+ if changes is None:
print 'List available by typing `rules`'
print
+ else:
+ self._changed(changes)
def do_exit(self, _):
"""
print 'No results.'
return
for val, bindings in results:
- #if not bindings:
- # print ' ', _repr(val)
- print ' ', _repr(val), 'where', drepr(dict(bindings))
+ print _repr(val), 'where', drepr(dict(bindings))
print
def do_query(self, q):
def _changed(self, changed):
if not changed:
return
- print '============='
+
+ print
+ print 'Changes'
+ print '======='
for x, v in sorted(changed.items()):
print '%s = %s.' % (x, _repr(v))
+ print
# def _changed_subscriptions(self, changed):
#
return _random() * (b - a) + a
def split(s, delim='\s+'):
- return _todynalist(re.split(delim, s))
+ return todynalist(re.split(delim, s))
def pycall(name, *args):
"""
Temporary foreign function interface - call Python functions from dyna!
"""
+ args = tuple(topython(x) for x in args)
x = eval(name)(*args)
- if isinstance(x, list):
- return _todynalist(x)
+ return todyna(x)
+
+def todyna(x):
+ if isinstance(x, (list, tuple)):
+ return todynalist(x)
+ return x
+
+def topython(x):
+ if isinstance(x, (Cons, Nil)):
+ return x.aslist
return x
+def todynalist(x):
+ return _todynalist(list(x))
+
def _todynalist(x):
if not x:
return Nil
__add__ = __sub__ = __mul__ = notimplemented
-from term import Term
class Cons(Term):
+
def __init__(self, head, tail):
self.head = head
self.tail = tail
assert isinstance(tail, (Cons, _Nil)), tail
Term.__init__(self, 'cons/2', (head, tail))
self.aggregator = Aggregator()
- def tolist(self):
- return [self.head] + self.tail.tolist()
- def __repr__(self):
- return repr(self.tolist())
-
- def __iter__(self):
-# return iter([(x,(x,),x) for x in self.tolist()])
- for a in self.tolist():
+ self.aslist = [self.head] + self.tail.aslist
- if not isinstance(a, Term):
- yield a, (None,), a
+ def __repr__(self):
+ return '[%s]' % (', '.join(map(_repr, self.aslist)))
- else:
- yield a, (None,), a
+# def __iter__(self):
+# for a in self.aslist:
+# if not isinstance(a, Term):
+# yield a, (None,), a
+# else:
+# yield a, (None,), a
def __eq__(self, other):
try:
- return self.tolist() == other.tolist()
+ return self.aslist == other.aslist
except AttributeError:
return False
+
class _Nil(Term):
def __init__(self):
Term.__init__(self, 'nil/0', ())
self.aggregator = Aggregator()
-
- def tolist(self):
- return []
+ self.aslist = []
def __repr__(self):
return '[]'
def lexer(term):
return re.findall('"[^"]*"' # string
'|[a-z][a-zA-Z_0-9]*' # functor
- '|[A-Z][a-zA-Z0-9_]*' # variable
- '|[(), ]+' # parens and comma
+ '|[A-Z_][a-zA-Z0-9_]*' # variable
+ '|[(), \[\]|]+' # parens and comma
'|[^(), ]+', term) # everything else
-def subst(term, v, show_vars=False):
+def subst(term, v):
"""
>>> subst('f("asdf",*g(1,X, Y), X+1)', {'X': 1234})
'f("asdf",*g(1,1234, Y), 1234+1)'
"""
assert isinstance(v, dict)
-
- if show_vars:
- return ''.join((x + (red % ('=' + _repr(v[x]))) if x in v else x) for x in lexer(term))
-
return ''.join((_repr(v[x]) if x in v else x) for x in lexer(term))
-> > =============
+> >
+Changes
+=======
a = 1.
+
> DynaCompilerError:
Encountered error in input program:
Conflicting aggregators; rule <repl>
=====
0: a += b * c.
-> =============
+>
+Changes
+=======
b = 2.
+
>
Rules
=====
0: a += b * c.
1: b := 2.
-> =============
+>
+Changes
+=======
a = 6.
c = 3.
+
>
Rules
=====
-> > =============
+> >
+Changes
+=======
a = 1.
-> =============
+
+>
+Changes
+=======
b = 1.
-> =============
+
+>
+Changes
+=======
a = 2.
+
>
Rules
=====
a = 2.
b = 1.
-> > >
+>
+Changes
+=======
+a = 1.
+
+>
+Changes
+=======
+b = null.
+
+>
Solution
========
a = 1.