The PyMonad Library
Here's the comparison:
list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
List(range(10))
[range(0, 10)]
The List() functor did not evaluate the range() object, it just preserved it without
being evaluated. The PyMonad.List() function is useful to collect functions without
evaluating them. We can evaluate them later as required:
x= List(range(10))
x
[range(0, 10)]
list(x[0])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
We created a lazy List object with a range() object. Then we extracted and
evaluated a range() object at position 0 in that list.
A List object won't evaluate a generator function or range() object; it treats any
iterable argument as a single iterator object. We can, however, use the * operator
to expand the values of a generator or the range() object.
Note that there are several meanings for * operator: it is the built-in
mathematical times operator, the function composition operator defined
by PyMonad, and the built-in modifier used when calling a function
to bind a single sequence object as all of the positional parameters of
a function. We're going to use the third meaning of the * operator to
assign a sequence to multiple positional parameters.
Here's a curried version of the range() function. This has a lower bound of 1
instead of 0. It's handy for some mathematical work because it allows us to avoid
the complexity of the positional arguments in the built-in range() function.
@curry
def range1n(n):
if n == 0: return range(1,2) # Only 1
return range(1,n+1)
We simply wrapped the built-in range() function to make it curryable by the
PyMonad package.