Building Curried functions
--------------------------

	WARNING: Curried functions are currently broken.  All expected results
	in this doctest have been commented out.  Uncomment after fixing Curried
	class.

    xix.utils allows you to build curried functions (closures) using the class
    python.Curried.

    >>> from xix.utils.python import Curried

    Some basic examples
    -------------------

        >>> def three(a, b, c=4):
        ...     return a, b, c
        ...
        >>> curried = Curried(three, 2, 3, c=5)

        #>>> print curried()
        #(2, 3, 5)

        Supplying an additional argument to curried:

        >>> curried = Curried(three, 2, 3)

        #>>> print curried(c=20)
        #(2, 3, 20)

        Excution of wrapped function is defered until all positional arguments
        are consumed:

        >>> curried = Curried(three)
        >>> curried = curried(1)
        >>> curried = curried(2)

        #>>> print curried
        #(1, 2, 4)

        Or ...

        >>> curried = Curried(three)
        >>> curried = curried(5)

        #>>> print curried(7, c=8)
        #(5, 7, 8)

        >>> curried = Curried(three)
        >>> curried = curried(5)

        #>>> print curried(7, 8)
        #(5, 7, 8)

    Advanced Usage
    --------------

        Curried doesn't care about how many or how little args your function takes

        A function with no args:

        >>> def example():
        ...    return 1
        ...
        >>> curried = Curried(example)

        #>>> print curried()
        #1

        A function with one positional argument:

        >>> def example(a):
        ...    return 1, a
        ...
        >>> curried = Curried(example)

        #>>> print curried(0)
        #(1, 0)

        A function with one keyword arg:

        >>> def example(a=5):
        ...    return 1, a
        >>> curried = Curried(example)

        #>>> print curried()
        #(1, 5)

        Or ...

        >>> curried = Curried(example)

        #>>> print curried(a=2)
        #(1, 2)
        
        Same keyword arguments can be passed again in distinct calls:

        >>> def example(p, a=1, b=2, c=4):
        ...     return p, a, b, c
        ...
        >>> curried = Curried(example)
        >>> curried = curried(a=2)
        >>> curried = curried(a=7)
        >>> curried = curried(b=1)
        >>> curried = curried(b=8)

        #>>> print curried(None)
        #(None, 7, 8, 4)

    Exceptions:
    -----------

    Exceptions are delegated to final call to wrapped function:

    >>> def example(a, b, c):
    ...     return a, b, c
    ...
    >>> curried = Curried(example)

    #>>> print curried(1,2,3,4)
    #Traceback (most recent call last):
    #...
    #TypeError: example() takes exactly 3 arguments (4 given)


    Or ...

    >>> curried = Curried(example)
    >>> curried = curried(a=34)

    #>>> print curried(1,2,3)
    #Traceback (most recent call last):
    #...
    #TypeError: example() got multiple values for keyword argument 'a'


    Todo
    ----

    Think of more ways to break the code.
    
