from collections.abc import Callable, Iterable
from typing import TypeVar, overload

from .decorator import make_data_last

T = TypeVar('T')


@overload
def reverse(it: Iterable[T], /) -> Iterable[T]: ...


@overload
def reverse() -> Callable[[Iterable[T]], Iterable[T]]: ...


@make_data_last
def reverse(iterable: Iterable[T], /) -> Iterable[T]:
    """
    Yields the elements of the iterable from last to first.

    Accumulates the elements of the iterable in a list before yielding them.

    Parameters
    ----------
    iterable : Iterable[T]
        Iterable to reverse (positional-only).

    Returns
    -------
    Iterable[T]
        Iterable with elements in reverse order.

    Examples
    --------
    Data first:
    >>> list(R.reverse([1, 2, 3]))
    [3, 2, 1]

    Data last:
    >>> list(R.reverse()(range(1, 4)))
    [3, 2, 1]

    """
    yield from reversed(list(iterable))
