Functional Pascal triangle in Python (working version) This is actually a follow-up question of Yet another Pascal triangle in Python written in functional programming pattern, which is put on hold for posting broken code.

Again, this is my implementation of a Pascal program, which is used to print an n-order Pascal triangle. I write it to familiarize myself with Python's Functional Programming Modules. Some changes have been made to get the code work and make it more "functional"

#!/usr/bin/env python3

import operator
from itertools import starmap, tee


def pairwise(iterable):
    """
    s -&gt; (s0,s1), (s1,s2), (s2,s3), ...
    https://docs.python.org/3/library/itertools.html#itertools-recipes
    """
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

def pascal_row(n):
    """
    Return a generator that yields the nth row of a Pascal triangle
    """
    if n &lt; 2:
        return (x for x in [1])
    else:
        def dispatch():
            yield 1
            yield from starmap(operator.add, pairwise(pascal_row(n-1)))
            yield 1
        return dispatch()

def print_pascal(n):
    """
    Print an n-order Pascal triangle
    """
    if n &gt; 0:
        print_pascal(n-1)
        print(list(pascal_row(n)))

print_pascal(10)



  Output:

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]



Please let me know if this piece of code isn't reflecting the essence of functional programming correctly.
Your current code calls pascal_row O(n^2) times (put a print inside to see this) through recursion. You don't want to be repeating so much calculation. To cache the results:

from functools import lru_cache

@lru_cache(maxsize=None)
def pascal_row(n):


However then you can't be returning generators anymore because after one iteration they'll be exhausted and yet the caching will return the same generators repeatedly, so you won't get the right results. This is fine, there wasn't really much use in the generators. It was particularly weird to see (x for x in [1]).

You could return list(dispatch()) but there's a much better itertools way than successive yielding: chain.

return list(chain([1], starmap(operator.add, pairwise(pascal_row(n - 1))), [1]))


But really there's no need for all this. The Pythonic way would be:

return [1] + [a + b for a, b in pairwise(pascal_row(n - 1))] + [1]


which is still decently functional.

if n &lt; 2: implies that n might also be 0, -1, etc. You want to:


Make it clear to readers that n should not be that.
Make sure the program quickly ends in an error in such a case so that you can find the bug.


Therefore add an assert n == 1 in this case.

This comes out to:

@lru_cache(maxsize=None)
def pascal_row(n):
    """
    Return a list that yields the nth row of a Pascal triangle
    """
    if n &lt; 2:
        assert n == 1
        return [1]
    else:
        return [1] + [a + b for a, b in pairwise(pascal_row(n - 1))] + [1]


In my opinion the recursion in print_pascal is completely unnecessary and a simple for loop would be much better, but I suppose you want it that way for the exercise.

To be really functional you could ensure that your data structures are immutable and use tuples instead of lists, although it's less pretty:

if n &lt; 2:
    return (1,)
else:
    return (1,) + tuple(a + b for a, b in pairwise(pascal_row(n - 1))) + (1,)