The LOOP macro
T. Ogawa
hydroxide at inorbit.com
Mon Mar 22 21:02:36 EST 2004
(xposted to c.l.python)
Here is a partial implementation/proof of concept for Python... the
remainder is left as an exercise ;-). Working examples based on some
of the lisp examples previously posted are below. It doesn't use
anything particularly tricky (ie: no exec/eval/__metaclass__/__new__).
Using it is, of course, clumsier than loop for short examples where a
listcomp makes more sense, but apparently not really so for longer
ones...
[Use, share, enjoy - all at your own risk. Do not run nuclear
reactors or medical equipment using it]
###################################### BEGIN loop.py
class Loop(list):
class Max(object):
def __cmp__(self, other):
return 1
def fix(self, item, key, default):
if item is None:
item = self.curr
return item, self.d.get(key, default)
def collect(self, *args,**kwds):
try:
key = kwds["key"]
item = self.curr
except KeyError:
try:
key, item = args
except ValueError:
key = "_"
try:
item = args[0]
except IndexError:
item = None
item, val = self.fix(item, key, [])
val.append(item)
self.d[key] = val
def summing(self, key, item=None):
item, val = self.fix(item, key, 0)
self.d[key] = val + item
def minimizing(self, key, item=None):
item, val = self.fix(item, key, self.Max())
self.d[key] = min(val, item)
def maximizing(self, key, item=None):
item, val = self.fix(item, key, None)
self.d[key] = max(val, item)
def counting(self, key, item=None):
self.summing(key, 1)
def final(self):
key = self.d.keys()[0]
return self.d[key]
def __init__(self, mylist):
self.d = {}
for elem in mylist:
self.curr = elem
self.each()
final = self.final()
if isinstance(final, str):
self.append(final)
else:
try:
self.extend(final)
except TypeError:
self.append(final)
def __getattr__(self, attr):
if attr in self.d:
return self.d[attr]
return []
###################################### END loop.py
from random import random as rand
# Rob Warnock no.1
#
# def listcomp_js(mystrings):
# ", ".join(["'%s'"%word.replace("'", "''") for word in
mystrings])
class FixQuotes(Loop):
class Escape(Loop):
def each(self):
self.collect()
if self.curr == "'":
self.collect()
def final(self):
return "".join(self._)
def each(self):
self.collect("'%s'" % self.Escape(self.curr)[0])
def join_strings(mystrings):
return ", ".join(FixQuotes(mystrings))
x = ["Here", "is", "Bob's", "house", "and", "Charles'"]
print join_strings(x)
print
# Peter Siebel no. 1
#
# print [rand() for i in range(10)]
class MyLoop(Loop):
def each(self):
self.collect(rand())
print MyLoop(range(10))
print
# Peter Siebel no. 2
class MyLoop(Loop):
def each(self):
self.minimizing("mymin")
self.maximizing("mymax")
self.summing("mysum")
self.counting("mylen")
def final(self):
return self.mymin, self.mymax, self.mysum/float(self.mylen)
print MyLoop(range(100))
print
# Widget setup for the next examples
class Widget(object):
def __init__(self):
if rand() > 0.5:
self.is_good = True
self.colour = "red"
self.is_foo = True
self.is_bar = False
else:
self.is_bar = True
self.is_good = False
self.colour = "blue"
if rand() > 0.5:
self.is_foo = True
else:
self.is_foo = False
widgets = [Widget() for i in range(10)]
# Peter Siebel no. 3
#
# print [w for w in widgets if w.is_good]
class MyLoop(Loop):
def each(self):
widget = self.curr
if widget.is_good:
self.collect(widget)
print MyLoop(widgets)
print
# Peter Siebel no. 4
class MyLoop(Loop):
def each(self):
widget = self.curr
if widget.colour == "red":
self.counting("red")
elif widget.colour == "blue":
self.counting("blue")
self.counting("total")
def final(self):
return self.red, self.blue, self.total
print MyLoop(widgets)
print
# Peter Siebel no. 5b
class MyLoop(Loop):
def each(self):
widget = self.curr
is_foo = widget.is_foo
is_bar = widget.is_bar
if is_foo:
self.collect(key="foos")
if is_bar:
self.collect(key="bars")
if is_foo and is_bar:
self.collect(key="both")
def final(self):
return self.foos, self.bars, self.both
for widgetset in MyLoop(widgets):
print widgetset
More information about the Python-list
mailing list