Skip to content

ekampf/pymaybe

Folders and files

NameName
Last commit message
Last commit date
Jul 13, 2015
Nov 7, 2016
Nov 7, 2016
Jul 13, 2015
Jul 13, 2015
Aug 11, 2015
Jul 16, 2015
Jul 13, 2015
Jul 13, 2015
Jul 13, 2015
Jul 13, 2015
Jul 13, 2015
Jan 13, 2016
Jul 13, 2015
Jul 31, 2015
Jul 31, 2015
Jul 13, 2015

Repository files navigation

PyMaybe

https://travis-ci.org/ekampf/pymaybe.svg?branch=master https://coveralls.io/repos/ekampf/pymaybe/badge.svg?branch=master&service=github

A Python implementation of the Maybe pattern.

Installation

pip install pymaybe

Getting Started

from pymaybe import maybe
first_name = maybe(deep_hash)['account']['user_profile']['first_name'].or_else("<unknown>")

Documentation

Maybe monad is a programming pattern that allows to treat None values that same way as non-none values. This is done by wrapping the value, which may or may not be None to, a wrapper class.

The implementation includes two classes: Maybe and Something. Something represents a value while Nothing represents a None value. There's also a method maybe which wraps a regular value and and returns Something or Nothing instance.

>>> maybe("I'm a value")
"I'm a value"

>>> maybe(None);
None

Both Something and Nothing implement 4 methods allowing you to test their real value: is_some, is_none, get and or_else

>>> maybe("I'm a value").is_some()
True

>>> maybe("I'm a value").is_none()
False

>>> maybe(None).is_some()
False

>>> maybe(None).is_none()
True

>>> maybe("I'm a value").get()
"I'm a value"

>>> maybe("I'm a value").or_else(lambda: "No value")
"I'm a value"

>>> maybe(None).get()
Traceback (most recent call last):
...
Exception: No such element

>>> maybe(None).or_else(lambda: "value")
'value'

>>> maybe(None).or_else("value")
'value'

In addition, Something and Nothing implement the Python magic methods allowing you to treat them as dictionaries:

>>> nested_dict = maybe(nested_dict)
>>> nested_dict['store']['name']
'MyStore'

>>> nested_dict['store']['address']
None

>>> nested_dict['store']['address']['street'].or_else('No Address Specified')
'No Address Specified'

All other method calls on Something are forwarded to its real value:

>>> maybe('VALUE').lower()
'value'

>>> maybe(None).invalid().method().or_else('unknwon')
'unknwon'

Examples & Use Cases

The Maybe pattern helps you avoid nasty try..except blocks. Consider the following code:

try:
    url = rss.load_feeds()[0].url.domain
except (TypeError, IndexError, KeyError, AttributeError):
    url = "planetpython.org"

With Maybe you could simply do:

url = maybe(rss).load_feeds()[0]['url'].domain.or_else("planetpython.org")

Getting the current logged in user's name. Without maybe:

def get_user_zipcode():
    address = getattr(request.user, 'address', None)
    if address:
        return getattr(address, 'zipcode', '')

    return ''

With maybe:

def get_user_zipcode():
    return maybe(request.user).address.zipcode.or_else('')

Further Reading

Copyright and License

Copyright 2015 - Eran Kampf

About

A Python implementation of the Maybe pattern

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published