Tom
Tom

Reputation: 6342

(data:Any)=>println(data) vs data:Any=>println(data)

I came across the following scala code:

val x = 10 match {
  case _: Int => data: Any => println(data) // no issue
}

val y = data: Any => println(data) //compiling error

In the match case clause, I don't have to write data: Any => println(data) as (data: Any) => println(data)

But in val y = data: Any => println(data), I have to write as val y = (data: Any) => println(data). Why?

Upvotes: 0

Views: 68

Answers (2)

RAGHHURAAMM
RAGHHURAAMM

Reputation: 1099

The Difference in one is case statement with pattern matching another is assignment statement. In the first case we are essentially returning the value(result) of the right hand side of => as statement block as shown below.

scala> {data: Any => println(data)}
res0: Any => Unit = $$Lambda$1141/1699449247@71468613

scala> data: Any => println(data)
<console>:1: error: ';' expected but '=>' found.
       data: Any => println(data)
scala> val x = 10 match {
     |   case _: Int => val y = 56;data: Any => println(data) // no issue
     | }
x: Any => Unit = $$Lambda$1171/115016870@8f374de

The above statements considers everything after => will be considered as a statement block in case statement, but in the second case ( assignment - ie., assigning a function value ) it is not. Hence brackets around parameter declaration are necessary.

EDIT:

Though I have given the above answer as per my observation in scala REPL, I further thought that it will not clearly answer the Why? part of the question asked. I further did some more trails on how scala compiler behaves after investigating the exact error message we get when we type

val y = data:Int => println(data)

scala> val y = data:Int => println(data)
<console>:1: error: ';' expected but '(' found.
       val y = data:Int => println(data)

This seems to be due to the scala's feature of type inference of the val y.

In Scala type can be specified both explicitly wherever it is required and Scala compiler can implicitly infer type wherever it can. Here the type of y is to be inferred by the scala compiler in the first instance because it was not explicitly declared here. It is due to this attempt of the compiler the above error message occurred.

Now if we want to explicitly declare the type there are two ways in scala:

First way : val y : Int = 5

Second way : val y = 5:Int

Both of the above assignment statements are valid in scala.

Because in our specific assignment statement ie.,

val y = data:Any => println(data)

we are forcing scala to infer the type of y in the Second way shown above.

To infer the type of y, the scala compiler is attempting as explained below:

Here the compiler is assuming that data is a function defined somewhere before this line of code and the function is of type Int=>println(data). Then it is checking the validity of this type. The compiler determined that Int is a valid type but println(data) is not, because the valid type names cannot contain parentheses('(' char) and that is why the error message as above.

If we insert the right hand side of the above assignment statement in a block ie; between curly braces or putting the parameter declaration within parentheses, there will be no problem in inferring the type of y.

Or Using the First way, we can do this to compile without curly braces,

val y : Any => Unit = data =>println(data)


scala> val y : Any => Unit = data =>println(data)
y: Any => Unit = $$Lambda$1059/1854873748@799c8758

Hope this explains the why part of the question.

Upvotes: 2

Alexey Romanov
Alexey Romanov

Reputation: 170745

The relevant rule is

If an anonymous function (x: T) => e with a single typed parameter appears as the result expression of a block, it can be abbreviated to x: T => e.

The first case (case _: Int => data: Any => println(data)) satisfies this condition, the second one doesn't. But you can rewrite it to

val y = { data: Any => println(data) }

Upvotes: 3

Related Questions