[Python-checkins] r52671 - python/trunk/Doc/howto/functional.rst

andrew.kuchling python-checkins at python.org
Wed Nov 8 14:35:35 CET 2006


Author: andrew.kuchling
Date: Wed Nov  8 14:35:34 2006
New Revision: 52671

Modified:
   python/trunk/Doc/howto/functional.rst
Log:
Add section on the functional module

Modified: python/trunk/Doc/howto/functional.rst
==============================================================================
--- python/trunk/Doc/howto/functional.rst	(original)
+++ python/trunk/Doc/howto/functional.rst	Wed Nov  8 14:35:34 2006
@@ -1,7 +1,7 @@
 Functional Programming HOWTO
 ================================
 
-**Version 0.21**
+**Version 0.30**
 
 (This is a first draft.  Please send comments/error
 reports/suggestions to amk at amk.ca.  This URL is probably not going to
@@ -1141,6 +1141,144 @@
 that are intended for use in functional-style programs.
 
 
+The functional module
+=====================
+
+Collin Winter's `functional module <http://oakwinter.com/code/functional/>`__ 
+provides a number of more
+advanced tools for functional programming. It also reimplements
+several Python built-ins, trying to make them more intuitive to those
+used to functional programming in other languages.
+
+This section contains an introduction to some of the most important
+functions in ``functional``; full documentation can be found at `the
+project's website <http://oakwinter.com/code/functional/documentation/>`__.
+
+``compose(outer, inner, unpack=False)``
+
+The ``compose()`` function implements function composition.
+In other words, it returns a wrapper around the ``outer`` and ``inner`` callables, such
+that the return value from ``inner`` is fed directly to ``outer``.  That is,
+
+::
+
+        >>> def add(a, b):
+        ...     return a + b
+        ...
+        >>> def double(a):
+        ...     return 2 * a
+        ...
+        >>> compose(double, add)(5, 6)
+        22
+
+is equivalent to
+
+::
+
+        >>> double(add(5, 6))
+        22
+                    
+The ``unpack`` keyword is provided to work around the fact that Python functions are not always
+`fully curried <http://en.wikipedia.org/wiki/Currying>`__.
+By default, it is expected that the ``inner`` function will return a single object and that the ``outer``
+function will take a single argument. Setting the ``unpack`` argument causes ``compose`` to expect a
+tuple from ``inner`` which will be expanded before being passed to ``outer``. Put simply,
+
+::
+
+        compose(f, g)(5, 6)
+                    
+is equivalent to::
+
+        f(g(5, 6))
+                    
+while
+
+::
+
+        compose(f, g, unpack=True)(5, 6)
+                    
+is equivalent to::
+
+        f(*g(5, 6))
+
+Even though ``compose()`` only accepts two functions, it's trivial to
+build up a version that will compose any number of functions. We'll
+use ``reduce()``, ``compose()`` and ``partial()`` (the last of which
+is provided by both ``functional`` and ``functools``).
+
+::
+
+        from functional import compose, partial
+        
+        multi_compose = partial(reduce, compose)
+        
+    
+We can also use ``map()``, ``compose()`` and ``partial()`` to craft a
+version of ``"".join(...)`` that converts its arguments to string::
+
+        from functional import compose, partial
+        
+        join = compose("".join, partial(map, str))
+
+
+``flip(func)``
+                    
+``flip()`` wraps the callable in ``func`` and  
+causes it to receive its non-keyword arguments in reverse order.
+
+::
+
+        >>> def triple(a, b, c):
+        ...     return (a, b, c)
+        ...
+        >>> triple(5, 6, 7)
+        (5, 6, 7)
+        >>>
+        >>> flipped_triple = flip(triple)
+        >>> flipped_triple(5, 6, 7)
+        (7, 6, 5)
+
+``foldl(func, start, iterable)``
+                    
+``foldl()`` takes a binary function, a starting value (usually some kind of 'zero'), and an iterable.
+The function is applied to the starting value and the first element of the list, then the result of
+that and the second element of the list, then the result of that and the third element of the list,
+and so on.
+
+This means that a call such as::
+
+        foldl(f, 0, [1, 2, 3])
+
+is equivalent to::
+
+        f(f(f(0, 1), 2), 3)
+
+    
+``foldl()`` is roughly equivalent to the following recursive function::
+
+        def foldl(func, start, seq):
+            if len(seq) == 0:
+                return start
+
+            return foldl(func, func(start, seq[0]), seq[1:])
+
+Speaking of equivalence, the above ``foldl`` call can be expressed in terms of the built-in ``reduce`` like
+so::
+
+        reduce(f, [1, 2, 3], 0)
+
+
+We can use ``foldl()``, ``operator.concat()`` and ``partial()`` to
+write a cleaner, more aesthetically-pleasing version of Python's
+``"".join(...)`` idiom::
+
+        from functional import foldl, partial
+        from operator import concat
+        
+        join = partial(foldl, concat, "")
+
+
 Revision History and Acknowledgements
 ------------------------------------------------
 
@@ -1159,6 +1297,9 @@
 
 Version 0.21: Added more references suggested on the tutor mailing list.
 
+Version 0.30: Adds a section on the ``functional`` module written by 
+Collin Winter.
+
 
 References
 --------------------
@@ -1185,6 +1326,8 @@
 http://en.wikipedia.org/wiki/Coroutine:
 Entry for coroutines.
 
+http://en.wikipedia.org/wiki/Currying:
+Entry for the concept of currying.
 
 Python-specific
 '''''''''''''''''''''''''''


More information about the Python-checkins mailing list