docs: def replace(needle, with_=None, in_=None):
      """Replace occurrences of string(s) with other string(s) in (a) string(s).
  
      Unlike the built in :meth:`str.replace` method, this function provides
      clean API that clearly distinguishes the "needle" (string to replace),
      the replacement string, and the target string to perform replacement in
      (the "haystack").
  
      Additionally, a simultaneous replacement of several needles is possible.
      Note that this is different from performing multiple separate replacements
      one after another.
  
      Examples::
  
          replace('foo', with_='bar', in_=some_text)
          replace('foo', with_='bar').in_(other_text)
          replace('foo').with_('bar').in_(another_text)
          replace(['foo', 'bar']).with_('baz').in_(perhaps_a_long_text)
          replace({'foo': 'bar', 'baz': 'qud'}).in_(even_longer_text)
  
      :param needle: String to replace, iterable thereof,
                     or a mapping from needles to corresponding replacements
      :param with_: Replacement string, if ``needle`` was not a mapping
      :param in_: Optional string to perform replacement in
  
      :return: If all parameters were provided, result is the final string
               after performing a specified replacement.
               Otherwise, a :class:`Replacer` object is returned, allowing
               e.g. to perform the same replacements in many haystacks.
      """
      if needle is None:
          raise TypeError("replacement needle cannot be None")
      if not needle:
          raise ValueError("replacement needle cannot be empty")
  
      if is_string(needle):
          replacer = Replacer((needle,))
      else:
          ensure_iterable(needle)
          if not is_mapping(needle):
              if all(imap(is_pair, needle)):
                  needle = dict(needle)
              elif not all(imap(is_string, needle)):
                  raise TypeError("invalid replacement needle")
          replacer = Replacer(needle)
  
      if with_ is not None:
          ensure_string(with_)
          replacer = replacer.with_(with_)
  
      if in_ is not None:
          ensure_string(in_)
          return replacer.in_(in_)
  
      return replacer