# Path: auxlib/compat.py
# def isiterable(obj):


from functools import reduce
from collections import Mapping, Set
from .compat import isiterable, iteritems, odict, text_type
        The optional `key` argument specifies a one-argument predicate function
        like that used for `filter()`.  The `key` argument, if supplied, must be
        in keyword form.  For example:
        >>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
        4

    """
    return next((apply(x) for x in seq if key(x)), default() if callable(default) else default)


def firstitem(map, key=lambda k, v: bool(k), default=None, apply=lambda k, v: (k, v)):
    return next((apply(k, v) for k, v in map if key(k, v)), default)


def last(seq, key=lambda x: bool(x), default=None, apply=lambda x: x):
    return next((apply(x) for x in reversed(seq) if key(x)), default)


def call_each(seq):
    """Calls each element of sequence to invoke the side effect.

    Args:
        seq:

    Returns: None

    """
    try:
        reduce(lambda _, y: y(), seq)
    except TypeError as e:

# Path: auxlib/compat.py
# def isiterable(obj):


# Path: auxlib/collection.py
from functools import reduce
from collections import Mapping, Set
from .compat import isiterable, iteritems, odict, text_type

        The optional `key` argument specifies a one-argument predicate function
        like that used for `filter()`.  The `key` argument, if supplied, must be
        in keyword form.  For example:
        >>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
        4

    """
    return next((apply(x) for x in seq if key(x)), default() if callable(default) else default)


def firstitem(map, key=lambda k, v: bool(k), default=None, apply=lambda k, v: (k, v)):
    return next((apply(k, v) for k, v in map if key(k, v)), default)


def last(seq, key=lambda x: bool(x), default=None, apply=lambda x: x):
    return next((apply(x) for x in reversed(seq) if key(x)), default)


def call_each(seq):
    """Calls each element of sequence to invoke the side effect.

    Args:
        seq:

    Returns: None

    """
    try:
        reduce(lambda _, y: y(), seq)
    except TypeError as e:

        if text_type(e) != "reduce() of empty sequence with no initial value":