Dataflow in Python

I spent a little time playing around with operator overloading in Python, to create a Python module for doing dataflow programming. I got to the point where I can write code like this:

x = rock(1)
fact = factorial(x)
print fact.get()
x.set(6)
print fact.get()

However because python makes it much harder to work with statements than with expressions, the definition of factorial() is somewhat tortured:

one = rock(1)
two = rock(2)
def factorial(n):
    return _if(n < two, one, n*rock(factorial)(n-one))

Basically I had to turn the if-statement into an expression. And since expressions are always evaluated eagerly, I also had to wrap the recursive function call in order to make it lazily evaluated. It doesn't bother me that the code is sprinkled with calls to rock() to lift all the constants into dataflow-land, but it does bother me that the if statement got so mutilated. After all, part of the appeal of Python is its clear, indentation-based layout. And expressionification destroys that.

In fact, expressionification gets even worse if you're trying to use an iterative version of factorial. I still haven't figured out how to make a dataflow-capable version of this:

def factorial(n):
    result = 1
    while (n > 1):
        result *= n
        n -= 1
    return result

The problem, in essence, is that dataflow is based on creative interpretation of expressions. And I can't figure out how to turn statements into expressions, except by using full-blown functions. But it seems that full-blown functions can't have any mutable state. For example, this code gives the error "local variable 'n' referenced before assignment":

def foo(n):
    def bar():
       n += 1
       print n
    return bar
foo(1)()

So it appears that I'll have to package up all the state into a struct, and pass it in to the function definition. But that requires so much code that I expect it will completely obscure the intent of the function.

Posted on August 9, 2004 04:26 PM
More languages articles

Comments

You can store attributes on function objects. Does this do what you wanted?

def foo(n):
_ def bar():
_ _ bar.n += 1
_ _ return bar.n
_ bar.n = n
_ return bar

baz = foo(37)
qux = foo(100)
print baz(), qux(), baz(), qux()

Posted by: Damian Cugley at August 10, 2004 06:04 AM

Ah! Excellent! :)

Posted by: Kim at August 10, 2004 05:13 PM

I just found out about Python's inspect and parser modules. These offer the opportunity for me to write something like this:

def factorial(n):
    ...
factorial = dataflow_function(factorial)

Combine this with python's new decorator idea, and you have the beginnings of a workable macro system for Python.

Posted by: Kim at August 18, 2004 11:07 AM

Just found your blog and was perusing your old posts. I'm not sure if you keep up with comments on old posts, but just in case...

The usual method of making an 'if' like statement into an expression is to use the boolean operators 'and' and 'or'. Your if statement above could be rewritten:

return ( n < two and one ) or ( n*rock(factorial)(n-one) )

Posted by: John Eikenberry at February 9, 2005 12:34 PM
Post a comment









Remember info?




Prove you're human. Type "human":