Skip to content Skip to sidebar Skip to footer

Conjoin Function Made In Functional Style

Recently, reading Python 'Functional Programming HOWTO', I came across a mentioned there test_generators.py standard module, where I found the following generator: # conjoin is a s

Solution 1:

This seems to work, and it's still lazy:

defconjoin(gs):
    return [()] ifnot gs else (
        (val,) + suffix for val in gs[0]() for suffix in conjoin(gs[1:])
    )

defrange3():
    returnrange(3)

printlist(conjoin([range3, range3]))

Output:

[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

Example usage to show mutable state:

x = ""defmutablerange():
    global x
    x += "x"return [x + str(i) for i inrange(3)]

printlist(conjoin([range3, mutablerange]))

Output: (watch the increasing number of 'x's)

[(0, 'x0'), (0, 'x1'), (0, 'x2'), (1, 'xx0'), (1, 'xx1'), (1, 'xx2'), (2, 'xxx0'), (2, 'xxx1'), (2, 'xxx2')]

And if we use itertools.product:

x = ""print list(itertools.product(range3(), mutablerange()))

the result is the following:

[(0, 'x0'), (0, 'x1'), (0, 'x2'), (1, 'x0'), (1, 'x1'), (1, 'x2'), (2, 'x0'), (2, 'x1'), (2, 'x2')]

So, one clearly see, that itertools.product caches the values returned by the iterator.

Solution 2:

simple_conjoin uses the same basic building blocks -- loops, conditions, and yield -- as the building blocks of the itertools recipes. It also treats functions as data, a hallmark of functional programming.

Of course this is most useful when the iterators have side-effects, so that which values can be generated at each slot depend on the values iterated at previous slots.

This, however, is contrary to the way functional programming works. In functional programming, each function takes input and produces output, and reacts with the rest of the program in no other way.

In simple_conjoin, the functions take no input, and have side effects. This is central to it's use.

So while you can certainly write it in functional style, it won't be useful in simple translation.

You'd need to figure out a way to write it so it operated without side effects before you could produce a truly "functional" implementation.

Note: @recursive's answer is good, but if range3 had side effects it wouldn't be truly functional.

Post a Comment for "Conjoin Function Made In Functional Style"