Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add thread_some function (some-> macro) #379

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions toolz/curried/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
second,
thread_first,
thread_last,
thread_some,
)
from .exceptions import merge, merge_with

Expand Down
45 changes: 43 additions & 2 deletions toolz/functoolz.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
from .utils import no_default


__all__ = ('identity', 'thread_first', 'thread_last', 'memoize', 'compose',
'pipe', 'complement', 'juxt', 'do', 'curry', 'flip', 'excepts')
__all__ = ('identity', 'thread_first', 'thread_last', 'thread_some', 'memoize',
'compose', 'pipe', 'complement', 'juxt', 'do', 'curry', 'flip',
'excepts')


def identity(x):
Expand Down Expand Up @@ -94,6 +95,46 @@ def evalform_back(val, form):
return reduce(evalform_back, forms, val)


def thread_some(val, *forms):
""" Thread value through a sequence of functions/forms
with early termination if None occurred

>>> def double(x): return 2*x
>>> def inc(x): return x + 1
>>> thread_some(1, inc, double)
4

If the function expects more than one input you can specify those inputs
in a tuple. The value is used as the first input.

>>> def add(x, y): return x + y
>>> def pow(x, y): return x**y
>>> thread_some(1, (add, 4), (pow, 2)) # pow(add(1, 4), 2)
25

If some function return None, all computation will
fail, returning None.

>>> def div(x, y): (x / y) if y != 0 else None
>>> def double(x): return 2 * x
>>> def inc(x): return x + 1
>>> thread_some(-1, inc, (div, 10), double) is None
True

"""
next_val = val
for f in forms:
if next_val is None:
return None
if callable(f):
next_val = f(next_val)
elif isinstance(f, tuple):
func, args = f[0], f[1:]
args = (next_val,) + args
next_val = func(*args)
return next_val


def instanceproperty(fget=None, fset=None, fdel=None, doc=None, classval=None):
""" Like @property, but returns ``classval`` when used as a class attribute

Expand Down