https://github.com/hellerve/hawkweed
Yet another implementation of missing functions for Python
https://github.com/hellerve/hawkweed
currying datastructures functional monads
Last synced: 7 months ago
JSON representation
Yet another implementation of missing functions for Python
- Host: GitHub
- URL: https://github.com/hellerve/hawkweed
- Owner: hellerve
- License: mit
- Created: 2016-06-07T16:57:52.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2017-05-06T12:06:55.000Z (over 8 years ago)
- Last Synced: 2025-03-07T09:05:22.503Z (7 months ago)
- Topics: currying, datastructures, functional, monads
- Language: Python
- Size: 259 KB
- Stars: 20
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.rst
- License: LICENSE.txt
Awesome Lists containing this project
README
hawkweed
=============Yet another implementation of missing functions.
Installation
------------::
pip install hawkweed
Usage
-----hawkweed is roughly divided into three different parts: datatypes, monads and
functions. All the functions are exhaustively documented with pydoc, all the
parameters, the functions' time complexity (if applicable) and the return value
are given.Datatypes
---------Most of the datatypes implemented in hawkweed are mere wrappers around Python
standard datatypes. If the function does not return anything in the Python
datatype, this implementation will return ``self`` to allow for chaining.A notable exception is the largely unstable and undocumented ``Future`` class.
.. code-block:: python
from hawkweed import List, Dict, Set
List([1]).append(2).extend([3, None, 4]).remove_empty() # => List([1, 2, 3, 4])
List(range(10)).take(5) # => generator from 0 to 4
List(range(10)).drop(5) # => generator from 5 to 9
List(range(10)).take_while(lambda x: x < 5) # => generator from 0 to 4
List(range(10)).drop_while(lambda x: x < 5) # => generator from 4 to 9
List(range(10)).nth(3) # => generator yielding 0, 3, 6 and 9 (lazily); works with any subclass of Iterable
List(range(10)).reset(range(5)) # => List([0, 1, 2, 3, 4])Dict({1: 2, 3: 4}).reverse() # => Dict({2: 1, 4: 3})
Dict({1: 2, 3: 4, 2: None}).remove_empty() # => Dict({1: 2, 3: 4})
Dict({1: 2, 3: 4, None: "go away"}).remove_empty(filter_keys=True) # => Dict({1: 2, 3: 4})
Dict({1: 2, 3: 4, 2: 3}).remove_empty(fun=lambda x: x!=2) # => Dict({1: 2, 3: 4})
Dict({1: 2, 3: 4}).reduce(fun=lambda acc, k, v: acc + k + v, acc=0) # => 10
Dict({1: 2, 3: 4}).reduce(fun=lambda acc, k, v: acc + (k, v)) # => (1, 2, 3, 4)
Dict({1: 2, 3: 4, 5: 6}).pick(1, 5) # => Dict({1: 2, 5: 6})Set({1, 2, 3, 4}).remove_empty(fun=lambda x: x!=3) # => Set({1, 2, 4})
# And now for something completely different
Dict({
"foo": List([1, 2, 3, Dict({"bar": "baz"})])
}).get_in("foo", 3, "bar") # => "baz"
Dict({
"foo": List([1, 2, 3, Dict({"bar": "baz"})])
}).get_in("foo", 100, "bar") # => None
Dict({
"foo": List([1, 2, 3, Dict({"bar": "baz"})])
}).get_in("foo", 100, "bar", dflt="i am a default value") # => "i am a default value"
Dict({
"foo": List([1, 2, 3, Dict({"bar": "baz"})])
}).update_in("foo", 1, "bar", to="update") # => Dict({"foo": List([1, 2, 3, Dict({"bar": "update"})])})
# if you want to insert your own datatype, just inherit from hawkweed.Collection
# and implement get(key, dflt=None) and __setitem__Functions
---------All of the functions are standalone and curried whenever possible. They do not depend
on hawkweeds datatypes in any way... code-block:: python
from hawkweed import map, reduce, List, all, any, constantly, delay
map(inc, range(100)) # => range(1, 101)
incrementor = map(inc)
incrementor(List(range(100))) # => range(1, 101)
summator = reduce(add)
summator(range(5)) # => 10
all(lambda x: x > 100, [101, 102, 103]) # => True
any(lambda x: x > 10, [3, 5, 8]) # => False
constantly(10) # => an infinite generator of 10
delayed = delay(print, 'Hello, World!') # => this will return a variable that, when called, will compute the result of print with the argument 'Hello, World!'
# it will cache the result instead of recomputing it upon reevaluation, i.e. `delayed() or delayed()` will only print 'Hello, World!' onceA few other functions that you might expect from a functional programming library (``compose``,
``pipe``, ``identity``, ``apply``, ``flip``, ``curry`` and the like) are also implemented. They
should be intuitive and work as expected. If they do not or are not consider it a bug.Monads
------The implemented monads are: Identity, Maybe (Just/Nothing), Continuation, Either, IO, CachedIO,
and List (called ListM). do notation is also supported... code-block:: python
from hawkweed import doM, wrapM, Just
def doMe():
res1 = yield Just(1)
res2 = yield Just(10)
yield Just(res1+ res2)doM(doMe()) # => Just(11)
wrapM(Just(10)).real
# => 10; the wrapper will try to call the wrapped values' function whenever it does not exist in the monadThere is a callcc function and all of the functions in Haskell's Data.Maybe_ and Data.Either_ are implemented.
.. _Data.Maybe: https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Maybe.html
.. _Data.Either: https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Either.htmlHave fun!