2
votes

I'm trying to create a function that accepts two lists as arguments, and that each list is (a) not empty and (b) a list of a certain struct. Something like this would work for my needs:

def zip_sports_and_leagues(
  [%Sport{} | _tail] = sports,
  [%League{} | _tail] = leagues
) do
  # Do stuff with `sports` and `leagues`
end

I'm getting a "no function clause matching" error with that function when the first list has multiple items.

I've stripped down the code to this minimal example:

defmodule Test do
  def test([a | _tail], [b | _tail]) do
    1
  end
end

Test.test([1], [1])
=> 1

Test.test([1, 1], [1])
** (FunctionClauseError) no function clause matching in Test.test/2

    The following arguments were given to Test.test/2:

        # 1
        [1, 1]

        # 2
        [1]

Can someone tell me why I'm getting the function clause error and how I can fix it?

Thanks!

1

1 Answers

8
votes

The problem is that you're using the same name for the tail of both arguments: _tail. When a name in the argument of the function is used twice, the clause only matches when both have the same value. You can either rename one of them:

def zip_sports_and_leagues(
  [%Sport{} | _tail] = sports,
  [%League{} | _tail2] = leagues
) do
  # Do stuff with `sports` and `leagues`
end

or use _ which doesn't bind the value and can be used more than once:

def zip_sports_and_leagues(
  [%Sport{} | _] = sports,
  [%League{} | _] = leagues
) do
  # Do stuff with `sports` and `leagues`
end