filter and report multiple predicates - scala

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()

Related

Why Scala PartialFunction works without defining isDefinedAt?

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.

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
}

Scala check a Sequence of Eithers

I want to update a sequence in Scala, I have this code :
def update(userId: Long): Either[String, Int] = {
Logins.findByUserId(userId) map {
logins: Login => update(login.id,
Seq(NamedParameter("random_date", "prefix-" + logins.randomDate)))
} match {
case sequence : Seq(Nil, Int) => sequence.foldLeft(Right(_) + Right(_))
case _ => Left("error.logins.update")
}
}
Where findByUserId returns a Seq[Logins] and update returns Either[String, Int] where Int is the number of updated rows,
and String would be the description of the error.
What I want to achieve is to return an String if while updating the list an error happenes or an Int with the total number of updated rows.
The code is not working, I think I should do something different in the match, I don't know how I can check if every element in the Seq of Eithers is a Right value.
If you are open to using Scalaz or Cats you can use traverse. An example using Scalaz :
import scalaz.std.either._
import scalaz.std.list._
import scalaz.syntax.traverse._
val logins = Seq(1, 2, 3)
val updateRight: Int => Either[String, Int] = Right(_)
val updateLeft: Int => Either[String, Int] = _ => Left("kaboom")
logins.toList.traverseU(updateLeft).map(_.sum) // Left(kaboom)
logins.toList.traverseU(updateRight).map(_.sum) // Right(6)
Traversing over the logins gives us a Either[String, List[Int]], if we get the sum of the List we get the wanted Either[String, Int].
We use toList because there is no Traverse instance for Seq.
traverse is a combination of map and sequence.
We use traverseU instead of traverse because it infers some of the types for us (otherwise we should have introduced a type alias or a type lambda).
Because we imported scalaz.std.either._ we can use map directly without using a right projection (.right.map).
You shouldn't really use a fold if you want to exit early. A better solution would be to recursively iterate over the list, updating and counting successes, then return the error when you encounter one.
Here's a little example function that shows the technique. You would probably want to modify this to do the update on each login instead of just counting.
val noErrors = List[Either[String,Int]](Right(10), Right(12))
val hasError = List[Either[String,Int]](Right(10), Left("oops"), Right(12))
def checkList(l: List[Either[String,Int]], goodCount: Int): Either[String, Int] = {
l match {
case Left(err) :: xs =>
Left(err)
case Right(_) :: xs =>
checkList(xs, (goodCount + 1))
case Nil =>
Right(goodCount)
}
}
val r1 = checkList(noErrors, 0)
val r2 = checkList(hasError, 0)
// r1: Either[String,Int] = Right(2)
// r2: Either[String,Int] = Left(oops)
You want to stop as soon as an update fails, don't you?
That means that you want to be doing your matching inside the map, not outside. Try is actually a more suitable construct for this purpose, than Either. Something like this, perhaps:
def update(userId: Long): Either[String, Int] = Try {
Logins.findByUserId(userId) map { login =>
update(login.id, whatever) match {
case Right(x) => x
case Left(s) => throw new Exception(s)
}
}.sum
}
.map { n => Right(n) }
.recover { case ex => Left(ex.getMessage) }
BTW, a not-too-widely-known fact about scala is that putting a return statement inside a lambda, actually returns from the enclosing method. So, another, somewhat shorter way to write this would be like this:
def update(userId: Long): Either[String, Int] =
Logins.findByUserId(userId).foldLeft(Right(0)) { (sum,login) =>
update(login.id, whatever) match {
case Right(x) => Right(sum.right + x)
case error#Left(s) => return error
}
}
Also, why in the world does findUserById return a sequence???

How does the extractor work when the `unapply` function returns Boolean instead of Option?

I learned about extractors from the stairway book:
object Twice {
def apply(x: Int) = x * 2
def unapply(x: Int) = if(x % 2 == 0) Some(x / 2) else None
}
// outside pattern mathcing, Twice.apply(21) is called
val x = Twice(21)
x match {
// inside pattern matching, Twice.unapply(x) is called,
// the result Some(21) is matched against y,
// y gets the value 21
case Twice(y) => println(x + " is twice " + y)
case _ => println(x + " is odd.")
}
That's pretty straight forward. But today I read from some book on Play framework this code:
trait RequestExtractors extends AcceptExtractors {
//Convenient extractor allowing to apply two extractors.
object & {
def unapply(request: RequestHeader): Option[(RequestHeader, RequestHeader)] = Some((request, request))
}
}
//Define a set of extractors allowing to pattern match on the Accept HTTP header of a request
trait AcceptExtractors {
//Common extractors to check if a request accepts JSON, Html, etc.
object Accepts {
import play.api.http.MimeTypes
val Json = Accepting(MimeTypes.JSON)
val Html = Accepting(MimeTypes.HTML)
val Xml = Accepting(MimeTypes.XML)
val JavaScript = Accepting(MimeTypes.JAVASCRIPT)
}
}
//Convenient class to generate extractors checking if a given mime type matches the Accept header of a request.
case class Accepting(val mimeType: String) {
def unapply(request: RequestHeader): Boolean = request.accepts(mimeType)
def unapply(mediaRange: play.api.http.MediaRange): Boolean = mediaRange.accepts(mimeType)
}
def fooBar = Action {
implicit request =>
val xmlResponse: Node = <metadata>
<company>TinySensors</company>
<batch>md2907</batch>
</metadata>
val jsonResponse = Json.obj("metadata" -> Json.arr(
Json.obj("company" -> "TinySensors"),
Json.obj("batch" -> "md2907"))
)
render {
case Accepts.Xml() => Ok(xmlResponse)
case Accepts.Json() & Accepts.JavaScript() => Ok(jsonResponse)
}
}
How does the extractor work when the unapply function returns Boolean instead of Option? How do &, Accepts.Xml work here?
I can really tell you about the play framework, but if used in pattern matching an extractor returning a boolean signifies if the pattern matches. Thus if an extractor return true it means that the pattern matches the value. This is a good link about extractors and also covers this case:
http://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html
Generally you use extractors for two use cases:
1) Destructing an object, which means returning one or more values which represent the state of given object
2) You can also use extractors to turn an object into an object of another kind during pattern matching. I made a small example for this case:
class Division(val number: Int) {
}
object Division {
def unapply(divider: Division): Boolean = divider.number != 0
def unapply(divider: Int): Option[Division] = if (divider != 0) Some(new Division(divider)) else None
}
val divident = 15
val divider = 5
val y = divider match {
case Division(notZero) => divident / notZero.number //notZero is of type Division
case _ => throw new IllegalArgumentException()
}
Ok, I found a way to figure this out by making a minimal example:
object Unapply {
case class DividedBy(val number: Int) {
def unapply(divider: Int): Boolean = number % divider == 0
def unapply(divider: Double): Boolean = number % divider.toInt == 0
}
val x = DividedBy(15)
// y should be true
val y = 5 match {
// case DividedBy(15)() => true
case x() => true
case _ => false
}
}
The weird thing is that when you use DividedBy(15)() (commented out above), the code won't compile.
Update:
object Unapply {
case class Division(val number: Int) {
// def unapply(divider: Int): Boolean = number % divider == 0
def unapply(divider: Int): Option[(Int, Int)] = if (number % divider == 0) Some(number/divider, 0) else None
def unapply(divider: Double): Boolean = number % divider.toInt == 0
}
object Division {
def apply(number: Int) = new Division(number)
}
val divisionOf15 = Division(15)
// y should be true
val y = 5 match {
// case DividedBy(15)() => true
case divisionOf15(z, w) => s"$z, $w"
case _ => s"Not divisible"
}
val z = 5.0 match {
case divisionOf15() => "Divisible"
case _ => "Not divisible"
}
}
After some reading some old notes on the stairway book now I have a clearer understanding of this. The case class is a extractor factory.

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)
}
}