import re
from typing import Callable, Any


def safe_int(text: str) -> int | None:
    """
    Safe way to convert a string to an int.

    :param text: string to convert.
    :return: int if text converted to int, else None.
    """
    try:
        return int(text)
    except ValueError:
        return None

def safe_float(text: str) -> float | None:
    """
    Safe way to convert a string to a float.

    :param text: string to convert.
    :return: float if text converted to float, else None.
    """
    try:
        return float(text)
    except ValueError:
        return None

def parse_list(
        text: str,
        split_by: None | str | re.Pattern = None,
        converter: Callable[[str], Any] = None
        ) -> list:

    """
    Parses a text string and returns a list of elements.

    :param text: The input text to be split.
    :param split_by: The delimiter used for splitting.
                     If None (default), uses str.split() which splits by any whitespace
                     and discards empty strings. Can be a string or a compiled re.Pattern.
    :param converter: Callable[[str], Any] to be applied to each element after splitting
                      (e.g., int, float, str.strip). If None, elements remain as strings.
    :raises TypeError: If 'split_by' is of an unsupported type.
    :return: List of parsed and optionally converted elements.
    """

    if split_by is None or isinstance(split_by, str):
        _list = text.split(split_by)
    elif isinstance(split_by, re.Pattern):
        _list = re.split(split_by, text)
    else:
        raise TypeError('split_by must be None, str or re.Pattern.')

    if converter:
        return [converter(i) for i in _list]
    return _list
