Why does this code need an empty string or semicolon?

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 did not put a semicolon or an empty line before println, it will not compile:

Recursive value aFact needs type

+5
source share
3 answers

All this talk about recursive function and type is a red herring. Scala grammar does not allow postfix operators anywhere except at 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 specifications:

Expr        ::= (Bindings | [β€˜implicit’] id | β€˜_’) β€˜=>’ Expr
              | Expr1
Expr1       ::= β€˜if’ β€˜(’ Expr β€˜)’ {nl} Expr [[semi] else Expr]
              | β€˜while’ β€˜(’ Expr β€˜)’ {nl} Expr
              | β€˜try’ β€˜{’ Block β€˜}’ [β€˜catch’ β€˜{’ CaseClauses β€˜}’]
                [β€˜finally’ Expr]
              | β€˜do’ Expr [semi] β€˜while’ β€˜(’ Expr ’)’
              | β€˜for’ (β€˜(’ Enumerators β€˜)’ | β€˜{’ Enumerators β€˜}’)
              | {nl} [β€˜yield’] Expr
              | β€˜throw’ Expr
              | β€˜return’ [Expr]
              | [SimpleExpr β€˜.’] id β€˜=’ Expr
              | SimpleExpr1 ArgumentExprs β€˜=’ Expr
              | PostfixExpr
              | PostfixExpr Ascription
              | PostfixExpr β€˜match’ β€˜{’ CaseClauses β€˜}’
PostfixExpr ::= InfixExpr [id [nl]]

, PostfixExpr , if case : _* . , , , , , - match.

, ? , , , . BlockStat a Block, , .

, , -, . :

    val aFact = a!
    println("factorial of " + a + " is " + aFact)

:

    val id = id id
    id ( stringLit id id id stringLit id id )

:

    val id = id id id ( expr )
    val Pattern2 = SimpleExpr1 id SimpleExpr1 ArgumentExprs
    val Pattern2 = InfixExpr
    val Pattern2 = Expr
    val PatDef
    PatVarDef
    Def
    BlockStat

, infix , . , , , , .

+10

!

a ! println("factorial of " + a + " is " + aFact)

, , , .

aFact, , Scala , , .

!

+6

The following code compiles:

package it.onof.scalaDemo

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:Int = a.!
        println("factorial of " + a + " is " + aFact)
  }
}
+1
source

All Articles