Elixir: Rational Numbers import conflict

Compiling 1 file (.ex)
    error: imported Kernel.abs/1 conflicts with local function
    │
 60 │   def abs(a) do
    │       ^
    │
    └─ lib/rational_numbers.ex:60:7: RationalNumbers (module)


== Compilation error in file lib/rational_numbers.ex ==
** (CompileError) lib/rational_numbers.ex: cannot compile module RationalNumbers (errors have been logged)

Can’t compile my code because of a naming conflict with the imported ‘abs’ function from the Kernel module.

Are you importing Kernel?

If you don’t import it, you can still call it with its qualified name: Kernel.abs(value)

The exercise is to implement various functions for use with rational numbers. One of the functions is named ‘abs’ and should return the absolute value of a rational number.

I’m not trying to use the Kernel.abs function. When the code is interpreted it gets to the ‘abs’ function definition that is supposed to be implemented as a part of the solution to the exercise and it raises the error for the conflict.

I am not importing Kernel, so I have to assume that it gets imported behind the scenes when the tests are ran for this exercise

Can we see your full code please? Published solutions as recently as 19 hours ago are passing so we’d need more information to debug.

defmodule RationalNumbers do
  @type rational :: {integer, integer}

  @doc """
  Add two rational numbers
  """
  @spec add(a :: rational, b :: rational) :: rational
  def add(a, b) do
    {a_num, a_den} = a
    {b_num, b_den} = b

    x = a_num * b_den + b_num * a_den
    y = a_den * b_den
    reduce({x, y})
  end

  @doc """
  Subtract two rational numbers
  """
  @spec subtract(a :: rational, b :: rational) :: rational
  def subtract(a, b) do
    {a_num, a_den} = a
    {b_num, b_den} = b

    x = a_num * b_den - b_num * a_den
    y = a_den * b_den
    reduce({x, y})
  end

  @doc """
  Multiply two rational numbers
  """
  @spec multiply(a :: rational, b :: rational) :: rational
  def multiply(a, b) do
    {a_num, a_den} = a
    {b_num, b_den} = b

    x = (a_num * a_den)
    y = (b_num * b_den)
    reduce({x, y})
  end

  @doc """
  Divide two rational numbers
  """
  @spec divide_by(num :: rational, den :: rational) :: rational
  def divide_by(num, den) do
    {num_a, num_b} = num
    {den_a, den_b} = den

    x = num_a * den_b
    y = num_b * den_a
    reduce({x, y})
  end

  @doc """
  Absolute value of a rational number
  """
  @spec abs(a :: rational) :: rational
  def abs(a) do
    IO.puts(a)
  end

  @doc """
  Exponentiation of a rational number by an integer
  """
  @spec pow_rational(a :: rational, n :: integer) :: rational
  def pow_rational(a, n) do
    {a, n}
  end

  @doc """
  Exponentiation of a real number by a rational number
  """
  @spec pow_real(x :: integer, n :: rational) :: float
  def pow_real(x, n) do
    {x, n}
  end

  @doc """
  Reduce a rational number to its lowest terms
  """
  @spec reduce(a :: rational) :: rational
  def reduce(a) do
    {a1, a2} = a
    gcd = Integer.gcd(abs(a1), abs(a2))
    {div(a1, gcd), div(a2, gcd)}
  end
end

The issue is probably here:

Those abs calls should be prefixed with your module name so the compiler understands which abs is being used.

1 Like

Ah yeah that makes sense. Totally forgot I was using those there.
Thanks.

1 Like