viralogic / py-enumerable

A Python module used for interacting with collections of objects using LINQ syntax
MIT License
187 stars 24 forks source link

Stop using exceptions as control flows #27

Closed dagoltz closed 2 years ago

dagoltz commented 5 years ago

Exceptions as control flow are considered an antipattern (1 source for example).

py-enumerable should stop using exceptions as an internal control flow. For example:

    def element_at_or_default(self, n):
        """
        Returns element at given index or None if no element found
            * Raises IndexError if n is greater than the number of elements in
            enumerable
        :param n: index as int object
        :return: Element at given index
        """
        try:
            return self.element_at(n)
        except NoElementsError:
            return None

It's true that by definition "element_at" should raise an exception, that doesn't mean that "element_at_or_default" should use it as is and catch that exception. There should probably be an inner helper function used by both functions, that allow a more natural control flow.

Example:

def _element_at(self, n)
    result = list(itertools.islice(self.to_list(), max(0, n), n + 1, 1))
    if len(result) == 0:
        None, False
    return result[0], True

def element_at(self, n):
    """
    Returns element at given index.
        * Raises NoElementsError if no element found at specified position
    :param n: index as int object
    :return: Element at given index
    """
    element, element_found = self._element_at(n)
    if not element_found:
        raise NoElementsError(u"No element found at index {0}".format(n))
    return element

def element_at_or_default(self, n):
    """
    Returns element at given index or None if no element found
        * Raises IndexError if n is greater than the number of elements in
        enumerable
    :param n: index as int object
    :return: Element at given index
    """
    element, _ = self._element_at(n)
    return element

This kind of flow should be implemented throughout the code base