Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dna-encoding doesn't detect tail-recursion within a case expression #410

Open
patrickjaberg opened this issue Nov 19, 2023 · 1 comment
Open

Comments

@patrickjaberg
Copy link

Based on my understanding, it seems that using a case expression for pattern matching, rather than a function head, prevents the automated analyzer from detecting tail recursion.

From what I've read, using a single function head with at top-level case expression for pattern matching should result in essentially the same thing as using multiple function heads, once they are compiled. If that's correct, then it seems the analyzer should be able to detect tail recursion in the case expression variant shown (commented out) below.

It's also possible that there's a gap in my understanding and having the recursive call "wrapped" in a case expression results in a solution that isn't tail-recursive. 😄

  def encode(dna) do
    _encode(dna, <<>>)
  end

  # The analyzer says this function IS NOT tail recursive
  # defp _encode(dna, acc) do
  #  case dna do
  #    [] -> acc
  #    [c | rest] -> _encode(rest, <<acc::bits, encode_nucleotide(c)::4>>)
  #  end
  # end

  # The analyzer says this function IS tail recursive
  defp _encode([], acc), do: acc
  defp _encode([c | rest], acc), do: _encode(rest, <<acc::bits, encode_nucleotide(c)::4>>)
@angelikatyborska
Copy link
Member

Honestly, this issue is a bit above my skill level 😛

using a single function head with at top-level case expression for pattern matching should result in essentially the same thing as using multiple function heads, once they are compiled

I have no idea whether that's true. But I figured out a way to check. TL;DR: yes, it is the same, and I created a repo with my results: https://github.com/angelikatyborska/case-vs-multiple-clause-function

Still, I don't think we will be able to fix this in the analyzer. The analyzer does a simple check of the AST - is the last call in the function body a call to itself? If yes, that's "tail call recursion" for the purpose of learning on this platform. This is very simplified compared to what the Elixir compiler does when trying to optimize our code, but what else is the analyzer supposed to do?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants