Why do I receive a FunctionClauseError ("no function clause matching") in this Elixir program, translated from Erlang?

10,904

Just to expand on the problem and why you received the error you did:

Capitalized identifiers are treated as aliases for atoms. For example:

iex(1)> N == :Elixir.N
true

So when you have the following code:

iex(1)> defmodule Test do
...(1)> def foo, do: IO.puts "testing"
...(1)> end
iex(2)> Test.foo
testing

It's the same as saying

iex(3)> :Elixir.Test.foo
testing

Since uppercase identifiers are treated as symbols, you essentially wrote the following program:

defmodule Cater do
  def cut(0), do: 1
  def cut(:Elixir.N) when :Elixir.N>0, do: :Elixir.N + cut(:Elixir.N-1)
end

This is valid, because you can pattern match on atoms in the argument list, and :Elixir.N > 0 is a valid expression.

iex(1)> N > 0
true

Consider the following Elixir program and output:

iex(1)> defmodule Cater do
...(1)> def cut(0), do: IO.puts "cut(0)"
...(1)> def cut(N) when N > 0, do: IO.puts "cut(N)"
...(1)> end
iex(2)> Cater.cut(0)
cut(0)
iex(3)> Cater.cut(N)
cut(N)
iex(4)> Cater.cut(:Elixir.N)
cut(N)
iex(5)> Cater.cut(1)
** (FunctionClauseError) no function clause matching in Cater.cut/1
    iex:2: Cater.cut(1)

So, the reason you got the seemingly strange error message no function clause matching in Cater.cut/1 is that there's technically nothing wrong with your program (except for the actual function body of cut(N)—it would raise an ArithmeticError, which Elixir warns you about at compile time); it's perfectly valid, it just doesn't do what you wanted it to do/what you thought it did.

Share:
10,904

Related videos on Youtube

jpsthecelt
Author by

jpsthecelt

Updated on June 04, 2022

Comments

  • jpsthecelt
    jpsthecelt almost 2 years

    **So, I've worked with Erlang, before, and am pretty comfortable with it. I am just trying to learn Elixir.

    I was recently trying to translate a 'lazy caterers' example into elixir and am befuddled as to why it either doesn't compile, or compiles with a warning and doesn't work. What am I missing, here; Any ideas? The erlang code and 'run' are as follows:**

    jps@GRASSKEET ~/dev/erlang
    $ cat cater.erl
    
        -module(cater).
        -export([cater/1]).
        cater(0) -> 1;
        cater(N) when N>0 -> N + cater(N-1).
    
    jps@GRASSKEET ~/dev/erlang
    $ erl
    Eshell V6.3  (abort with ^G)
    1> c("cater.erl").
    {ok,cater}
    2> cater:cater(10).
    56
    3>*
    

    When I write Cater.ex like so, it gets an error that doesn't make sense to me:

    jps@GRASSKEET ~/dev/elix
    $ cat Cater.ex
    
        defmodule Cater do
          def cut(0), do: 1
          def cut(N) when N>0, do: N + cut(N-1)
        end
    
    jps@GRASSKEET ~/dev/elix
    $ iex
    Interactive Elixir (1.0.4) - press Ctrl+C to exit (type h() ENTER for help)
    iex(1)> c("Cater.ex")
    Cater.ex:1: warning: redefining module Cater
    Cater.ex:3: warning: this expression will fail with ArithmeticError
    [Cater]
    iex(2)> Cater.cut(10)
    ** (FunctionClauseError) no function clause matching in Cater.cut/1
        Cater.ex:2: Cater.cut(10)
    iex(2)>
    
    • jpsthecelt
      jpsthecelt almost 9 years
      Arrrrgh! What a moron I am. As soon as I posted this, I had a 'feeling', went back and editted, and 'sure enough', elixir didn't like the fact that my variable-names were capitalized. Once I changed all Ns to n, it properly compiled and ran. So sorry to bother y'all
    • jjbohn
      jjbohn almost 9 years
      Happens to the best of us :)
    • Pascal
      Pascal almost 9 years
      Maybe you could change the title, so people can retrieve your post easily: I also had this trouble trying elixir, where everything remind erlang, but everything is different :o)
  • José Valim
    José Valim almost 9 years
    It is also worth pointing out that the exactly same issue would happen going from Elixir to Erlang. If you use Elixir's lowercase variables in Erlang, they will be atoms, and you will have exactly the same error. :D
  • jpsthecelt
    jpsthecelt almost 9 years
    This is great! It really helps me understand the two languages.
  • jpsthecelt
    jpsthecelt almost 9 years
    Well, I see this question as very helpful to explain the semantic vs. syntactic differences within a new and exciting language; especially from the point-of-view of the beginner's 4-line program that was seemingly correct. I like Jose's note that the same is true in the 'reverse-direction'.I appreciate anyone's ideas to reword it to be clearer -- perhaps 'semantic differences in variable declarations btw. Elixir and Erlang'? TIA, jps
  • jpsthecelt
    jpsthecelt almost 9 years
    Hmmm; how about 'atoms vs. variables' in Elixir/Erlang, or 'arth error on elixir/erlang '+' --> BTW, BinaryMuse's explanation was very helpful in understanding why both pascal and I had initially made the same mistake. Finding a way to add this to S/O will help provide a quick solution/explanation for those professional programmers who are 'stumped'. [incidentally, making the reverse edits [all n to N for the erlang program], produced a similar 'arithmentic error in line 4' from erlc). Thx.