Why Scala PartialFunction works without defining isDefinedAt? - scala

It looks First and Second are the same, but why?
First
val iter = List(1, 2, 3, 4, 5).iterator
val first = iter.collect(new PartialFunction[Int, Int]{
def apply(i: Int) = i
def isDefinedAt(i: Int) = i > 0 && i < 3
})
first.foreach((println(_)))
Second
val iter2 = List(1, 2, 3, 4, 5).iterator
val second = iter2.collect {
case i:Int if i > 0 && i < 3 => i
}
second.foreach((println(_)))
Is it because the Scala compiler automatically converts
{ case i:Int if i > 0 && i < 3 => i } into the implelentation form of First with generating isDefinedAt from if i > 0 && i < 3 part?
Also, case i:Int if i > 0 && i < 3 => i is Case class pattern matching, if I am correct. However, in scala/src/library/scala/PartialFunction.scala, there is no Case class definition for PartialFunction.
trait PartialFunction[-A, +B] extends (A => B)
Then why this case class pattern match works?
I suppose Scala compiler does lots of implicit works intelligently but it confuses me to understand what is happening and how to write Scala code.
If there are good references, instead of language or compiler specifications, to understand
Scala code syntax and Scala way of writing code, please suggest.

Is it because the Scala compiler automatically converts { case i:Int if i > 0 && i < 3 => i } into the implelentation form of First with generating isDefinedAt from **if i > 0 && i < 3 ** part?
Yes, the exact translation is given in Pattern Matching Anonymous Functions. Here it'll be
new PartialFunction[Int, Int]{
def apply(x: Int) = x match {
case i:Int if i > 0 && i < 3 => i
}
def isDefinedAt(x: Int) = x match {
case i:Int if i > 0 && i < 3 => true
case _ => false
}
}
Note the difference with your first example in apply! You can still call it when isDefined is false.
Also, case i:Int if i > 0 && i < 3 => i is Case class pattern matching, if I am correct
If anything, it's the other way around; case classes are called that way because they can be pattern-matched and pattern matching uses case keyword in Scala.

Yes, the compiler converts the second version into a PartialFunction[Int,Int] (because that is what collect takes).
There is no case class matching here, and it is not even matching on type because the value must be Int (and therefore the type declaration in the second version is not required).
The style guide gives lots on tips on how Scala is typically written.

For your example
object Main {
def f = (1 to 5).collect { case i if i > 0 && i < 3 => i }
}
The compiler-generated partial function defines applyOrElse because it is more efficient than the naive idiom:
if (pf.isDefinedAt(x)) pf.apply(x) else ???
Showing that implementation, which is similar to what is described in the spec:
$ scalac -Vprint:typer pf.scala
[[syntax trees at end of typer]] // pf.scala
package <empty> {
object Main extends scala.AnyRef {
def <init>(): Main.type = {
Main.super.<init>();
()
};
def f: IndexedSeq[Int] = scala.Predef.intWrapper(1).to(5).collect[Int](({
#SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Int,Int] with java.io.Serializable {
def <init>(): <$anon: Int => Int> = {
$anonfun.super.<init>();
()
};
final override def applyOrElse[A1 <: Int, B1 >: Int](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Int]: Int): Int #unchecked) match {
case (i # _) if i.>(0).&&(i.<(3)) => i
case (defaultCase$ # _) => default.apply(x1)
};
final def isDefinedAt(x1: Int): Boolean = ((x1.asInstanceOf[Int]: Int): Int #unchecked) match {
case (i # _) if i.>(0).&&(i.<(3)) => true
case (defaultCase$ # _) => false
}
};
new $anonfun()
}: PartialFunction[Int,Int]))
}
}
where AbstractPartialFunction defines
def apply(x: T1): R = applyOrElse(x, PartialFunction.empty)
Here is an external link to a change to use applyOrElse. The improved PartialFunction dates back to 2012. Probably the feature is under-documented or under-advertised. Some information is available by expanding the Scaladoc for PartialFunction. For some reason, that link shows orElse, so you'd actually have to scroll back for applyOrElse. It seems documentation is hard.

Related

How do I call a method that only exists on one of the 2 types in an Either?

I have an array of objects of type Either[A, B]. If I know for a particular element whether it is an A or a B, how do I call a method on it that only exists on one of the 2 types. For example:
import scala.util.Random
object EitherTest extends App {
def newObj(x: Int): Either[A,B] = {
if (x == 0)
Left(new A())
else
Right(new B())
}
val random = new Random()
val randomArray = (0 until 10).map(_ => random.nextInt(2))
val eitherArray = randomArray.map(newObj)
(0 until 10).foreach(x => randomArray(x) match {
case 0 => eitherArray(x).aMethod()
case 1 => eitherArray(x).bMethod()
case _ => println("Error!")
})
}
class A {
def aMethod() = println("A")
}
class B {
def bMethod() = println("B")
}
When I compile this code, the lines
case 0 => eitherArray(x).aMethod()
case 1 => eitherArray(x).bMethod()
both have the error "value aMethod is not a member of Either[A,B]". How can I solve this?
I don't know why fold doesn't get the respect it deserves. It can be so useful.
eitherArray.foreach(_.fold(_.aMethod(), _.bMethod()))
Well, you can do it if you exctract the logic to another method, and do some pattern matching over the value Either, then check if it is Right or Left, and that's it!
object HelloWorld {
import scala.util.Random
def main(args: Array[String]) {
val random = new Random()
val randomArray = (0 until 10).map(_ => random.nextInt(2))
val eitherArray = randomArray.map(EitherTest.newObj)
(0 until 10).foreach(x => randomArray(x) match {
case 0 => EitherTest.callmethod(eitherArray(x))
case 1 => EitherTest.callmethod(eitherArray(x))
case _ => println("Error!")
})
println("Hello, world!")
}
}
class EitherTest
object EitherTest {
def callmethod(ei : Either[A,B]) = {
ei match {
case Left(a) => a.aMethod()
case Right(b) => b.bMethod()
}
}
def newObj(x: Int): Either[A,B] = {
if (x == 0)
Left(new A())
else
Right(new B())
}
}
class A {
def aMethod() = println("A")
}
class B {
def bMethod() = println("B")
}
Will print for you, for one random example:
A
B
A
B
A
A
A
B
B
B
Hello, world!
Basically, the way you do with Either is projections: Either.left gives you the projection of the left type, and Either.right gives you that of the right.
The projections are somewhat similar to options, in that they can be empty (if your Either is a Right, then the left projection is empty and vice versa), and you can use the usual monadic transformations with them, like map, flatMap, foreach, getOrElse etc.
Your example, could look like this:
randomArray.foreach { either =>
either.left.foreach(_.aMethod)
either.right.foreach(_.bMethod)
}
You could also use pattern-matching instead, that's less general, but, perhaps looks a bit clearer in this case:
randomArray.foreach {
case Left(a) => a.aMethod
case Right(b) => b.bMethod
}

filter and report multiple predicates

This is a kind of cosmetic Scala question. A list with objects needs to be filtered on the objects' attributes. I need to report if the first check on the attribute results in an empty list. Simplified code:
case class Account (id: Int, balance: Float)
def doFilter(list: List[Account], focusId: Int, thresHold: Float): List[Account] = {
list.filter(_.id == focusId)
// ## if at this point if the list is empty, an error log is required.
.filter(_.balance >= thresHold)
}
var accounts = List(Account(1, 5.0f), Account(2, -1.0f), Account(3, 10f), Account(4, 12f))
println(s"result ${doFilter(accounts, 1, 0f)}")
Of course I can split up the filter statements and check the intermediate result but I was hoping I could do it more scala way.. I thought something like.
list.filter(_.id == focusId)
match { case List() => { println "error"; List()}
case _ => _}
But that doesn't work. Is there a functional (or fluent) way to implement the desired behaviour?
The following code is a slight modification from this SO answer from Rex Kerr.
implicit class KestrelPattern[A](private val repr: A) extends AnyVal {
def tee[B](f: A => B) = { f(repr); repr } // B is thrown away (Unit)
}
He called it tap. I chose tee because of the similarity to the unix tee command.
Usage:
scala> List[Int](3,5,7).tee{x => if (x.isEmpty) println("ERROR")}.sum
res42: Int = 15
scala> List[Int]().tee{x => if (x.isEmpty) println("ERROR")}.sum
ERROR
res43: Int = 0
If you need it once, then logging an intermediate result is, probably, the simplest way. If you need this at several places, you can make the code a bit nicer using extension methods:
implicit class ListOps[+A](val list: List[A]) extends AnyVal {
def logIfEmpty(): List[A] = {
if (list.isEmpty) {
println("Error: empty list")
// or whatever; you can even pass it as an argument
}
list
}
}
Then you can use it like this:
def doFilter(list: List[Account], focusId: Int, thresHold: Float): List[Account] = list
.filter(_.id == focusId)
.logIfEmpty()
.filter(_.balance >= thresHold)
The pattern matching works, the error of your code comes from the fact that you are trying to return _ in the second case, you may want to check here and here for why this could be a problem:
accounts.filter(_.id == 1) match {
case List() => { println("error"); List() }
case x => x.filter(_.balance > 1.0)
}
// res19: List[Account] = List(Account(1,5.0))
accounts.filter(_.id == 5) match {
case List() => { println("error"); List() }
case x => x.filter(_.balance > 1.0)
}
// error
// res20: List[Account] = List()

How does isDefinedAt method work when case statements are used?

In this explanation of partial functions in scala, an case statement is used as follows:
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}
Then it says:
Although this code doesn’t explicitly implement the isDefinedAt
method, it works exactly the same as the previous divide function
definition
The previous divide function explicitly defines apply and isDefined methods as follows:
val divide = new PartialFunction[Int, Int] {
def apply(x: Int) = 42 / x
def isDefinedAt(x: Int) = x != 0
}
I see that the compiler is doing some sort of magic here, but I'm curious about the nature of the mechanism: is the guard in the case (if d != 0) extracted into body of isDefined at the background? What about multiple case statements with their own guards? The domain of the function is defined in the case statement(s), so that must be how the compiler is building the implementation of isDefined behind the scenes.
Am I right?
First of all, the explanation is wrong, since both the presented examples don't work the same:
scala> val a: PartialFunction[Int, Int] = {
| case i if i != 0 => 42 / i
| }
a: PartialFunction[Int,Int] = <function1>
scala> val b = new PartialFunction[Int, Int] {
| def apply(i: Int) = 42 / i
| def isDefinedAt(i: Int) = i != 0
| }
b: PartialFunction[Int,Int] = <function1>
scala> a(0)
scala.MatchError: 0 (of class java.lang.Integer)
at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:253)
at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:251)
at $anonfun$1.applyOrElse(<console>:7)
at $anonfun$1.applyOrElse(<console>:7)
at scala.runtime.AbstractPartialFunction$mcII$sp.apply$mcII$sp(AbstractPartialFunction.scala:36)
... 33 elided
scala> b(0)
java.lang.ArithmeticException: / by zero
at $anon$1.apply$mcII$sp(<console>:8)
... 33 elided
But the core of it is true, the compiler converts the code in the case clauses to a boolean expression for the isDefinedAt method and then the function itself as the apply method (hence the MatchError if the value is not defined)
For a general example, a function like this:
val a = PartialFunction[A, B] {
case <clause A> => <action A>
case <clause B> => <action B>
}
Is compiled as:
val a = new PartialFunction[A, B] {
def isDefinedAt(a: A) = a match {
case <clause A> => true
case <clause B> => true
case _ => false
}
def apply(a: A) = a match {
case <clause A> => <action A>
case <clause B> => <action B>
}
}
Here is the spec that defines this behavior.
I believe it's working because of the available case supported by the pattern matching definition.
The divide2 method has one matching case: x != 0 given x of type Int, therefore, if your value is anything else than that, it should return false.

How do I inherit shared code in a Scala unapply function?

I have Scala code with some boilerplate, and I figure it's Scala, so I must be doing something wrong. I need some help figuring out how to remove the redundancies.
trait Number {
val x: Int
}
case class EvenNumber(x: Int) extends Number
object EvenNumber {
def unapply(s: String): Option[EvenNumber] = {
val x = s.toInt
if (x % 2 == 0) Some(EvenNumber(x))
else None
}
}
case class OddNumber(x: Int) extends Number
object OddNumber {
def unapply(s: String): Option[OddNumber] = {
val x = s.toInt
if (x % 2 == 1) Some(OddNumber(x))
else None
}
}
In this simple example there are even numbers and odd numbers which are subtypes of a general number type. Both even and odd numbers have extractors that allow them to be created from strings. This enables use cases like the following.
scala> "4" match {case EvenNumber(n) => n;case _ => None}
// returns EvenNumber(4)
scala> "5" match {case EvenNumber(n) => n;case _ => None}
// returns None
scala> "4" match {case OddNumber(n) => n;case _ => None}
// returns None
scala> "5" match {case OddNumber(n) => n;case _ => None}
// returns OddNumber(5)
The source code for the two extractors is identical except for the result of the x % 2 operation (0 or 1) and the extracted type (EvenNumber or OddNumber). I'd like to be able to write the source once and parameterize on these two values, but I can't figure out how. I've tried various type parameterizations to no avail.
The Stackoverflow question "How to use extractor in polymorphic unapply?" is related but different, because my implementing classes are not distinguished by the types they contain by rather by the string inputs they recognize.
Here is a revised version of the code incorporating comments I received in addition to the original post. (As is often the case, the first round of answers helped me figure out what my real question was.)
import scala.util.Try
trait Number {
val x: Int
}
object NumberParser {
def parse[N <: Number](s: String, remainder: Int, n: Int => N): Option[N] =
Try {s.toInt}.toOption.filter(_ % 2 == remainder).map(n(_))
}
case class EvenNumber(x: Int) extends Number
object EvenNumber {
def unapply(s: String): Option[EvenNumber] = NumberParser.parse(s, 0, EvenNumber(_))
}
case class OddNumber(x: Int) extends Number
object OddNumber {
def unapply(s: String): Option[OddNumber] = NumberParser.parse(s, 1, OddNumber(_))
}
Factoring out a static NumberParser.parse function is a reasonable solution. I would still like to have have syntactic sugar that obviated my repeating unapply lines in all of my case classes, since in a more complicated example that had more than two that could get ugly. Does anyone know of a way to do this?
More crucially, the use case I really want to support is the following.
scala> "5" match {case EvenNumber(n) =>n;case OddNumber(n) => n;case _ => None}
// returns OddNumber(5)
scala> "4" match {case EvenNumber(n) =>n;case OddNumber(n) => n;case _ => None}
// returns EvenNumber(4)
scala> "x" match {case EvenNumber(n) =>n;case OddNumber(n) => n;case _ => None}
// returns None
Again this is fine for two cases, but in a different application where there are more than two it can become unmanageable. I want to write a single case
s match {case Number(n) => n; case _ => None}
which returns OddNumber(5), EvenNumber(4), None as above.
I can't figure out how to write my Number supertype to support this. Is it possible in Scala?
Edit: Wrote a description of my final answer with additional commentary in "Runtime Polymorphism with Scala Extractors".
Why inherit?
object Mod2Number {
def parse[A <: Number](s: String, i: Int, n: Int => A) = {
val x = s.toInt
if (x % 2 == i) Some(n(x))
else None
}
}
case class EvenNumber(x: Int) extends Number
object EvenNumber {
def unapply(s: String) = Mod2Number.parse(s, 0, n => EvenNumber(n))
}
But if even that is too much noise you can go one step further:
trait Makes[A <: Number] {
def apply(i: Int): A
def mod: Int
def unapply(s: String): Option[A] = {
val x = s.toInt
if (x % 2 == mod) Some(apply(x))
else None
}
}
case class EvenNumber(x: Int) extends Number
object EvenNumber extends Makes[EvenNumber] { def mod = 0 }
I guess you should catch exceptions on toInt - exceptions in pattern matching is something strange.
object EvenNumber {
def unapply(s: String): Option[Int] = Try{s.toInt}.toOption.filter{_ % 2 == 0}
}
object OddNumber {
def unapply(s: String): Option[Int] = Try{s.toInt}.toOption.filter{_ % 2 == 1}
}
You could extract similar code, but I don't think it's useful here:
class IntFilter(f: Int => Boolean) {
def unapply(s: String): Option[Int] = Try{s.toInt}.toOption.filter(f)
}
object EvenNumber extend IntFilter(_ % 2 == 0)
object OddNumber extend IntFilter(_ % 2 == 1)
For edited question:
s match {case Number(n) => n; case _ => None}
You could create object Number like this:
object Number{
def unapply(s: String): Option[Number] = Try{s.toInt}.toOption.collect{
case i if i % 2 == 0 => EvenNumber(i)
case i if i % 2 == 1 => OddNumber(i)
}
}

hashCode in case classes in Scala

I've read that Scala'a case class construct automatically generates a fitting equals and hashCode implementation. What does exactly the generated code look like?
As my professor used to say, only the code tells the truth! So just take a look at the code that is generated for:
case class A(i: Int, s: String)
We can instruct the Scala compiler to show us the generated code after the different phases, here after the typechecker:
% scalac -Xprint:typer test.scala
[[syntax trees at end of typer]]// Scala source: test.scala
package <empty> {
#serializable case class A extends java.lang.Object with ScalaObject with Product {
..
override def hashCode(): Int = ScalaRunTime.this._hashCode(A.this);
...
override def equals(x$1: Any): Boolean = A.this.eq(x$1).||(x$1 match {
case (i: Int,s: String)A((i$1 # _), (s$1 # _)) if i$1.==(i).&&(s$1.==(s)) => x$1.asInstanceOf[A].canEqual(A.this)
case _ => false
});
override def canEqual(x$1: Any): Boolean = x$1.$isInstanceOf[A]()
};
}
So you can see that the calculation of the hash code is delegated to ScalaRunTime._hashCode and the equality depends on the equality of the case class' members.
The generated hashCode just calls scala.runtime.ScalaRunTime._hashCode, which is defined as:
def _hashCode(x: Product): Int = {
val arr = x.productArity
var code = arr
var i = 0
while (i < arr) {
val elem = x.productElement(i)
code = code * 41 + (if (elem == null) 0 else elem.hashCode())
i += 1
}
code
}
So what you get is elem1 * 41**n + elem2 * 41**(n-1) .. elemn * 1, where n is the arity of your case class and elemi are the members of that case class.
Please be aware that the previous answers on this question are a bit outdated on the hashCode part.
As of scala 2.9 hashCode for case classes uses MurmurHash: link.
MurmurHash produces good avalanche effect, good distribution and is CPU friendly.
Looks like things have changed; using Mirko's example case class A(i: Int, s: String)I get:
override <synthetic> def hashCode(): Int = {
<synthetic> var acc: Int = -889275714;
acc = scala.runtime.Statics.mix(acc, i);
acc = scala.runtime.Statics.mix(acc, scala.runtime.Statics.anyHash(s));
scala.runtime.Statics.finalizeHash(acc, 2)
};
and
override <synthetic> def equals(x$1: Any): Boolean = A.this.eq(x$1.asInstanceOf[Object]).||(x$1 match {
case (_: A) => true
case _ => false
}.&&({
<synthetic> val A$1: A = x$1.asInstanceOf[A];
A.this.i.==(A$1.i).&&(A.this.s.==(A$1.s)).&&(A$1.canEqual(A.this))
}))
};