Reputation: 18971
I am new to Scala and I am trying to decode its constructs, I learned about pattern matching and the syntax is similar to Java switch statement
val x: Int = Random.nextInt(10)
x match {
case 0 => "zero"
case 1 => "one"
case 2 => "two"
case _ => "other"
}
This code here is pretty obvious and readable. I came across partial functions which are pretty obvious and clear what are they
A partial function is a function that does not provide an answer for every possible input value it can be given.
What I am confused about is using case
in the body of a partial function
like this:
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d // WHAT IS THIS ?!
}
I don't understand how case
is used without match
statement, how does this is interpreted by Scala, how it is read, is it a method, a class or another construct ?, what other ways I can use case
without match
statement
Edit:
I tried to play around with this case and still don't get it. For example
val SomeFun: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 1000 / d
case f: Int if f != 2 => 100 / f
case m: Int if m != 1 => 10 / m
}
How does this work?
Trying this gives an error
val SomeFun = {
case d: Int if d != 0 => 1000 / d
case f: Int if f != 2 => 100 / f
case m: Int if m != 1 => 10 / m
}
Error:(29, 17) missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
Is case without match used anywhere else outside a partial function?
Upvotes: 5
Views: 1245
Reputation: 170745
It is a pattern-matching anonymous function as described in the specification.
Trying this gives an error
val SomeFun = ...
This is because parameter type needs to be known, just like for "normal" anonymous functions x => ...
. The difference is that in a pattern-matching anonymous function there's no place to specify the parameter type directly (equivalent to (x: Int) => ...
), so there must be an expected type e.g. val SomeFun: PartialFunction[Int, Int]
or val SomeFun: Int => Int
.
val SomeFun: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 1000 / d
case f: Int if f != 2 => 100 / f
case m: Int if m != 1 => 10 / m
}
gets translated to
val SomeFun: PartialFunction[Int, Int] = new PartialFunction[Int, Int] {
override def apply(x: Int) = x match {
case d: Int if d != 0 => 1000 / d
case f: Int if f != 2 => 100 / f
case m: Int if m != 1 => 10 / m
}
override def isDefined(x: Int) = x match {
case d: Int if d != 0 => true
case f: Int if f != 2 => true
case m: Int if m != 1 => true
case _ => false
}
}
Upvotes: 5
Reputation: 3519
I will try to answer this question:
I don't understand how case is used without match statement, how does this is interpreted by Scala, how it is read, is it a method, a class or another construct ?
mainly by referring to this article which I will be quoting and paraphrasing.
The reason this works:
val f: (Any) => String = {
case i: Int => "Int"
case d: Double => "Double"
case _ => "Other"
}
is that the compiler interprets it as an anonymous function.
when you create val function, all you’re really doing with code like this is assigning a variable name to an anonymous function.
To support that first statement, Section 15.7 of Programming in Scala states:
A sequence of cases in curly braces can be used anywhere a function literal can be used.
So it is not really different than using the same syntax inside inside filter
or collect
.
The code in the above essentially creates a Function1
object. As this source explains:
The main distinction between PartialFunction and scala.Function1 is that the user of a PartialFunction may choose to do something different with input that is declared to be outside its domain.
Upvotes: 4
Reputation: 1815
It means that a partial function will be applied only if the input param can match case expression.
The actual class generated is something like this:
val divide = new PartialFunction[Int, Int] {
def apply(x: Int) = 42 / x
def isDefinedAt(x: Int) = x != 0
}
Using orElse you can apply or handle multiple definitions:
funcForInt orElse funcForDouble orElse funcForString
Nice composition?
Edit:
val SomeFun: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 1000 / d
case f: Int if f != 2 => 100 / f
case m: Int if m != 1 => 10 / m
}
The above is using anonymous class feature. If you remove the variable's type, you are just giving it a block expression with some case expressions which compiler can't really use.
Ref: https://www.james-willett.com/scala-anonymous-classes
Upvotes: 6