kachayev/fn.py

Implement iters.every and iters.some

Closed this issue · 7 comments

Implement every and some in fn.iters that are influenced by Clojure's every? and some respectively.

How about

every = F(partial(map)) >> all
some = F(partial(map)) >> any

for the implementations?

Each of the functions takes a predicate and an iterable. For example,

assert every(_ % 2 == 0, [2, 4, 6])
assert some(_ % 2 == 0, [1, 3, 4])

some in Clojure works other way: http://clojuredocs.org/clojure_core/clojure.core/some.

some clojure.core
(some pred coll)
Returns the first logical true value of (pred x) for any x in coll, else nil.

Thanks for pointing it out. I realised every? is a predicate whereas some is not. Here's a new version of some.

some = F(partial(map)) >> partial(filter, _) >> first

or

def some(f, iterable):
    return first(filter(_, map(f, iterable)))

Some examples to follow

>>> assert some(_ % 2 == 0, [1, 2, 3])
>>> assert some(_ % 2 == 0, [1, 3, 5]) is None

# Note: 0 and None are logical false in Python
>>> d = {"a": 1, "b": 2, "c": 0}
>>> f = lambda k: d.get(k)
>>> assert some(f, ["c", "B", "a"]) == 1
>>> assert some(f, ["C", "B", "A"]) is None

I can rename every to isevery to make a clearer distinction from some.

Also, are you happy to have them in fn.iters? Just thought fn.op might be a better place to store them.

First variant for some is ok. I meant this one:

some = F(partial(map)) >> partial(filter, _) >> first

It's good example of composition usage. fn.iters is definitely ok.

Name every is also ok (isevery is not so intuitive).

Oh, we can actually replace partial(filter, _) with iters.compact.

compact = partial(filter, None)  # already in iters.py
some = F(partial(map)) >> compact >> first  # new version using iters.compact

Also, are you happy for me to implement not_every and not_any as well? Similar to Clojure's not-every? and not-any? respectively.

Implementation:

not_every = every >> not_
not_any = F(partial(map)) >> any >> not_

Examples:

assert not_every(_ % 2 == 1, [1, 2, 3])
assert not_every(_ % 2 == 1, [1, 3]) == False
assert not_any(_ % 2 == 1, [2, 4, 6])
assert not_any(_ % 2 == 1, [1, 2, 3]) == False

I think not-every? and no-any? are overkill.