Dzhu
Dzhu

Reputation: 4381

Scala type inference on overloaded method

Given this code:

class Rational(n: Int, d: Int) {
  require(d != 0)
  private val g = gcd(n.abs, d.abs)
  val numerator = n / g
  val denominator = d / g

  def this(n: Int) = this(n, 1)

  override def toString = numerator + "/" + denominator

  def +(r: Rational) = new Rational(numerator * r.denominator + r.numerator * denominator, denominator * r.denominator)

  def *(r: Rational) = new Rational(numerator * r.numerator, denominator * r.denominator)

  def +(i: Int) = new Rational(i) + this

  private def gcd(a: Int, b: Int) : Int = {
    if (b == 0) a else gcd(b, a % b)
  }

}

why isn't scala able to infer that +(i: Int) returns a Rational number? (fsc gives overloaded method + needs result type error)

if i change that method to:

def +(i: Int): Rational = { new Rational(i) + this }

It works...

Upvotes: 14

Views: 4303

Answers (2)

Barak Itkin
Barak Itkin

Reputation: 4877

I found a thread in the scala mailing list with exactly the same question here. The answers there explains a bit why is it required to give the return type. After investigating a bit more I also found this: When is a return type required for methods in Scala. If I should quote the answer from there:

When Explicit Type Annotations Are Required.

In practical terms, you have to provide explicit type annotations for the following situations:

Method return values in the following cases:

  • When you explicitly call return in a method (even at the end).
  • When a method is recursive.
  • When a method is overloaded and one of the methods calls another. The calling method needs a return type annotation.
  • When the inferred return type would be more general than you intended, e.g., Any.

Upvotes: 26

Landei
Landei

Reputation: 54584

In this case it could infer the right type, but it just isn't clever enough. It's easy to construct some pathological examples with overloaded methods where things get really messy, so I guess that's why the Scala team decided to make a clear cut and require the return type. This is similar to recursive methods, where you need the result type, too, even though the compiler could infer it in many cases.

Upvotes: 3

Related Questions