def find(iterable, conditional):
    """
    Looks through each value in the list, returning the first one that passes a truth test 
    The function yields as soon as it finds an acceptable element, and doesn't traverse the entire iterable

    params: iterable, conditional
        iterable -> list, sequenece, set, dictionary, generator etc
        conditional -> a lambda or function that takes one or two inputs, first is element from iterable, second is index (optional)

    Examples:

    >>> list(_.find([1, 2, 3, 4, 5, 6], lambda x: x % 2 == 0))
    >>> [2]
    
    Since this returns a generator with a single value "next" can also be used to extract that value
    >>> next(_.find([1, 2, 3, 4, 5, 6], lambda x: x % 2 == 0))
    >>> 2

    TODO: What happens if nothing is matched, generator would raise an exception on next
    """
    for element in iterable:
        if conditional(element):
            yield element
            break
