I was reading about scala anonymous functions here and saw that they can take the format:
{ case p1 => b1 … case pn => bn }
However, I thought that this was how partial functions were written. In fact, in this blog post, the author calls a partial function an anonymous function. At first he says that collect
takes a partial function but then appears to call it an anonymous function ("collect can handle the fact that your anonymous function...").
Is it just that some anonymous functions are partial functions? If so, are all partial functions anonymous? Or are they only anonymous if in format like Alvin Alexander's example here:
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}
From the documentation on pattern matching anonymous functions that you linked:
If the expected type is SAM-convertible to
scala.Functionk[S1,…,Sk, R]
, the expression is taken to be equivalent to the anonymous function:(x1:S1,…,xk:Sk) => (x1,…,xk) match { case p1 => b1 … case pn => bn }
Here, each xi is a fresh name. As was shown here, this anonymous function is in turn equivalent to the following instance creation expression, where T is the weak least upper bound of the types of all bi.
new scala.Functionk[S1,…,Sk, T] { def apply(x1:S1,…,xk:Sk): T = (x1,…,xk) match { case p1 => b1 … case pn => bn } }
If the expected type is
scala.PartialFunction[S, R]
, the expression is taken to be equivalent to the following instance creation expression:new scala.PartialFunction[S, T] { def apply(x: S): T = x match { case p1 => b1 … case pn => bn } def isDefinedAt(x: S): Boolean = { case p1 => true … case pn => true case _ => false } }
Your first code snippet is a pattern matching anonymous function, but not necessarily a partial function. It would only be turned into a PartialFunction
if it was given to a method with a PartialFunction
parameter or assigned to a variable of type PartialFunction
.
So you are right that just some (pattern matching) anonymous functions are partial functions (AFAIK, function literals defined with fat arrows, such as x => x
, can only ever be used to create FunctionN
instances and not PartialFunction
instances).
However, not all partial functions are anonymous functions. A sugar-free way to define PartialFunction
s is extending the PartialFunction
trait (which extends Function1
) and manually overriding the isDefinedAt
and apply
methods. For example, divide2
could also be defined like this, with an anonymous class:
val divide2 = new PartialFunction[Int, Int] {
override def isDefinedAt(x: Int) = x != 0
override def apply(x: Int) = 42 / x
}
You probably won't see this very often, though, as it's a lot easier to just use pattern matching to define a PartialFunction.
In the blog post by Alvin Alexander you linked, the author refers to the pattern matching anonymous partial function literal as an anonymous function only because it happens to be both a partial function and an anonymous function. You could also define the function like so:
List(42, "cat").collect(new PartialFunction[Any, Int] {
def isDefinedAt(x: Any) = x.isInstanceOf[Int]
def apply(x: Any) = x match {
case i: Int => i + 1
}
})
It's no longer an anonymous function, although it's still an anonymous object that's the instance of an anonymous class. Or you could define a singleton object beforehand and then use that.
object Foo extends PartialFunction[Any, Int] {
def isDefinedAt(x: Any) = x.isInstanceOf[Int]
def apply(x: Any) = x match {
case i: Int => i + 1
}
}
List(42, "cat").collect(Foo)
No matter how you define it, though, it's a partial function.