Chapter 6
In Python, the product function can be defined recursively as follows:
def prodrc(collection):
if len(collection) == 0: return 1
return collection[0] * prodrc(collection[1:])
This is technically correct. It's a trivial rewrite from mathematical notation to
Python. However, it is less than optimal because it tends to create a large number of
intermediate list objects. It's also limited to only working with explicit collections;
it can't work easily with iterable objects.
We can revise this slightly to work with an iterable, which avoids creating any
intermediate collection objects. Following is a properly recursive product function
which works with an iterable source of data:
def prodri(iterable):
try:
head= next(iterable)
except StopIteration:
return 1
return head*prodri(iterable)
We can't interrogate an iterable with the len() function to see how many elements
it has. All we can do is attempt to extract the head of the iterable sequence. If
there are no items in the sequence, then any attempt to get the head will raise the
StopIteration exception. If there is an item, then we can multiply this item by the
product of the remaining items in the sequence. For a demo, we must explicitly create
an iterable from a materialized sequence object, using the iter() function. In other
contexts, we might have an iterable result that we can use. Following is an example:
prodri(iter([1,2,3,4,5,6,7]))
5040
This recursive definition does not rely on explicit state or other imperative features
of Python. While it's more purely functional, it is still limited to working with
collections of under 1000 items. Pragmatically, we can use the following kind of
imperative structure for reduction functions:
def prodi(iterable):
p= 1
for n in iterable:
p *= n
return p