case class MyInt(val i : Int) {
private def factorial(a : Int) : Int = a match {
case 0 => 1
case n => (n) * factorial(n-1)
}
def ! = factorial(i)
override def toString = i.toString
}
object MyInt {
implicit def intToMyInt(x : Int) = MyInt(x)
implicit def myIntToInt(x : MyInt) = x.i
}
import MyInt._
object Factorial {
def main(args: Array[String]): Unit = {
val a = 5
val aFact = a!
println("factorial of " + a + " is " + aFact)
}
}
If I don’t put a semicolon or an empty line before println it fails to compile:
recursive value aFact needs type
All this talk about recursive function and type is a red-herring. Scala’s grammar does not allow for postfix operators in any other place than the end of an expression. This is the grammar we are talking about: the syntax of things without any semantics. Here is the relevant grammar from the specs:
The only two places where
PostfixExprappears beside these are after theifon acasestatement and before: _*on an argument list. So, looking at that, we see that the only things that can appear on the right side of a postfix expression’s method name is a type ascription or amatch.So, what end expressions? Well, expressions appears in a lot of places in the grammar, so there’s a lot of things that could end it. In this particular example, the expression is a
BlockStatinside aBlock, so it must end with a semi-colon, which may be inferred or not.To infer this semi-colon, it is necessary that the next line must not be something that could be parsed as another kind of expression. In this particular case, we have this:
Now, let’s rewrite that from the point of view of the compiler:
These literals and identifiers are parsed like this:
So that looks like a valid infix expression to the compiler as he parsed your program. Afterwards, it noticed the types didn’t match, but it’s too late to go back and see if a semi-colon could be inferred.