Reputation: 6342
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
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
Reputation: 170745
The relevant rule is
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