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

from .decorator import make_data_last


@overload
def join(data: Iterable[Any], glue: str, /) -> str: ...


@overload
def join(glue: str, /) -> Callable[[Iterable[Any]], str]: ...


@make_data_last
def join(
    data: Iterable[Any],
    glue: str,
    /,
) -> str:
    """
    Joins the iterable with provided delimiter.

    The elements of the iterable are joined by:
    - casting them to a string and
    - concatenating them one to the other, with the provided glue string in between every two elements.

    Parameters
    ----------
    data : iterable
        Iterable to join (positional-only).
    glue : str
        Glue string (positional-only).

    Returns
    -------
    str
        Joined string.

    Examples
    --------
    Data first:
    >>> R.join([1, 2, 3], ",")
    '1,2,3'

    Data last:
    >>> R.join(",")(range(3))
    '0,1,2'

    """
    return glue.join(str(x) for x in data)
