New function for swap casing

I read how works functions upcase and downcase and try to think how to realize function swapcase.

in elixir/lib/elixir/unicode/unicode.ex line308

  # Swapcase

  def swapcase(string), do: swapcase(string, "")

  for {codepoint, upper, lower, _title} <- codes do
    cond do
      lower && codepoint != lower ->
        defp swapcase(unquote(codepoint) <> rest, acc) do
          swapcase(rest, acc <> unquote(lower))
        end
      upper && codepoint != upper ->
        defp swapcase(unquote(codepoint) <> rest, acc) do
          swapcase(rest, acc <> unquote(upper))
        end
      true -> nil
    end
  end

  defp swapcase(<<char, rest::binary>>, acc) do
    swapcase(rest, <<acc::binary, char>>)
  end

  defp swapcase("", acc), do: acc

Result:

iex(17)> r(String.Casing)                                      
warning: redefining module String.Unicode (current version defined in memory)
  unicode.ex:1

warning: redefining module String.Casing (current version defined in memory)
  unicode.ex:294

warning: redefining module String.Break (current version defined in memory)
  unicode.ex:379

warning: redefining module String.Normalizer (current version defined in memory)
  unicode.ex:489

{:reloaded, String.Casing,
 [String.Unicode, String.Casing, String.Break, String.Normalizer]}
iex(18)> String.Casing.swapcase("ПриВЕ!!ббю..WEr5%oe902kj elk")
"пРИве!!ББЮ..weR5%OE902KJ ELK"
iex(19)> 

The tests were successful

  test "swapcase" do
    test_string = "123 abcD 456 EFG HIJ ( %$#) kl mnop @ QRST = -_ uvwxyz"
    result_string = "123 ABCd 456 efg hij ( %$#) KL MNOP @ qrst = -_ UVWXYZ"
    assert String.swapcase(test_string) == result_string
    assert String.swapcase(String.swapcase(test_string)) == test_string
    assert String.swapcase("") == ""
  end

  test "swapcase utf8" do
    assert String.swapcase("& % # àáâ ãäå 1 2 ç æ") == "& % # ÀÁÂ ÃÄÅ 1 2 Ç Æ"
    assert String.swapcase("àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ") == "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ"
    assert String.swapcase("& % # ÀÁÂ ÃÄÅ 1 2 Ç Æ") == "& % # àáâ ãäå 1 2 ç æ"
    assert String.swapcase("ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ") == "àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ"
  end

  test "swapcase utf8 multibyte" do
    assert String.swapcase("straße") == "STRASSE"
    assert String.swapcase("áÜÈß") == "ÁüèSS"
  end

If this code fine, can i do PR?))
In ruby this function names “swapcase”. In elixir we may use different name like “reversecase”, “togglecase”.

1 Like

swapcase makes sense as a name for me. However I am curious about the use-cases for this as I’ve never come across one yet?

2 Likes

I too am skeptical about use cases, and concerned about longer compilation time for unicode.ex which already takes a while.

1 Like

Totally agree about the time of compilation.
To do this, we can combine more functions and creating downcase and upcase in one loop . As for the use of the function - with serious work with large strings , as well as being in order not to produce their own decisions and have a set of functionality comparable to the ruby.
I can reduce time of the compilation by price code readability. All three functions will be created with a single pass on the code list.

  # Swapcase, Upcase, Downcase

  def swapcase(string), do: swapcase(string, "")

  def downcase(string), do: downcase(string, "")

  def upcase(string), do: upcase(string, "")

  for {codepoint, upper, lower, _title} <- codes do
    cond do
      lower && codepoint != lower ->
        defp downcase(unquote(codepoint) <> rest, acc) do
          downcase(rest, acc <> unquote(lower))
        end
        defp swapcase(unquote(codepoint) <> rest, acc) do
          swapcase(rest, acc <> unquote(lower))
        end
      upper && codepoint != upper ->
        defp upcase(unquote(codepoint) <> rest, acc) do
          upcase(rest, acc <> unquote(upper))
        end
        defp swapcase(unquote(codepoint) <> rest, acc) do
          swapcase(rest, acc <> unquote(upper))
        end
      true -> nil
    end
  end

  defp swapcase(<<char, rest::binary>>, acc) do
    swapcase(rest, <<acc::binary, char>>)
  end

  defp swapcase("", acc), do: acc

  defp downcase(<<char, rest::binary>>, acc) do
    downcase(rest, <<acc::binary, char>>)
  end

  defp downcase("", acc), do: acc

  defp upcase(<<char, rest::binary>>, acc) do
    upcase(rest, <<acc::binary, char>>)
  end

  defp upcase("", acc), do: acc

  # End Swapcase, Upcase, Downcase
1 Like

I guess not coming from a Ruby background I don’t have the same concern about feature parity with Ruby that others do. Like Ben and Overmind while this might have some uses for some people I doubt it’s broadly useful. If you believe lots of others will need this, put a package up on Hex.pm. When it gets lots of downloads you’ll be able to make a better case for including it in the Unicode module.

I mean you can certainly submit a PR. If you feel that’s your best course of action, I’d bring up this subject on the Elixir Core list before submitting the PR. I don’t think the PR would get anywhere. But that’s just my guess, of course.

1 Like