Scala Option higher order functions instead of pattern matching - scala

What is the higher order function equivalent expression to the following?
def isRepeated:Boolean = {
prev match {
case Some(a) => a.prev match {
case Some(b) => b.equals(this)
case None => false
}
case None => false
}
}

I believe this is equivalent:
def isRepeated:Boolean = prev.exists(_.prev.exists(_.equals(this)))

Related

Scala matching high order function return value

Hello im trying to use case match with a high order function. if function return true do things same for false. Thank you.
def funk(ls:List[Int],f:Int=>Boolean):List[Int]=
{
f match
{
case true => do something
case false => do somethingelse
}
}
Looks like a good place to apply "andThen" for partial function:
Here is possibly what you need:
def funk(ls: List[Int], f: Int => Boolean): List[Int] = {
val z = f.andThen(r => r match {
case true => List(1, 2) // ..something
case false => List(3, 4) // somethingElse
})
// function application
z(5)
}
Just dig a bit around PartialFunction's:
http://www.scala-lang.org/api/current/scala/PartialFunction.html
you have to execute the function and pass the return value to the match case as
def funk(ls:List[Int],f:Int=>Boolean):List[Int]=
{
f(some integer value) match
{
case true => return a list of integers
case false => return a list of integers
}
}
for example
def funk(ls:List[Int],f:Int=>Boolean):List[Int]=
{
f(ls(0)) match
{
case true => List(1,2)
case false => List(4,3)
}
}

Scala multi-level pattern matching

I'm stuck with multi-level pattern matching, in the code below I want to match one particular case which is checked at several levels "cfe is Assignment, assignmentCfe.getRight is BinaryExpression, and so on", the solution looks ugly and I hope there is something better Scala can offer me. :)
def findAll(cfg: Cfg, consumer: Consumer[Violation]): Unit = {
val fa = new FlowAnalyzer
val states = fa.analyze(cfg)
states.foreach { case (cfe, state) => cfe match {
case assign: Assignment => assign.getRight match {
case expression: BinaryExpression => expression.getOperator match {
case Operator.Div | Operator.Rem => processDivisions()
case _ =>
}
case _ =>
}
case _ =>
}
case _ =>
}
}
How to get rid of these empty default cases in the end?
Another approach would be using nested conditions, but IntelliJ IDEA offers me to replace these conditions back to pattern matching
states.foreach { case (cfe, state) => if (cfe.isInstanceOf[Assignment]) {
val assignment = cfe.asInstanceOf[Assignment]
if (assignment.getRight.isInstanceOf[BinaryExpression]) {
val expression = assignment.getRight.asInstanceOf[BinaryExpression]
if (expression.getOperator == Operator.Div || expression.getOperator == Operator.Rem) processDivisions()
}
}}
Are Assignment and BinaryExpression themselves case classes? Or do they have corresponding unapply methods? If so, then you can nest pattern matches and ignore fields you don't care about. For example, something like:
def findAll(cfg: Cfg, consumer: Consumer[Violation]): Unit = {
val fa = new FlowAnalyzer
val states = fa.analyze(cfg)
states.foreach {
case (Assignment(_, BinaryExpression(_, _, Operator.Div | Operator.Rem)), _) => processDivisions()
case _ =>
}
}
This will at least cut the number of default matches down to 1.
If these are not case classes or don't have extractors, then you could consider writing your own if this is a common enough (anti)pattern in your code: http://docs.scala-lang.org/tutorials/tour/extractor-objects.html
One other idea is you could use the "pimp my library" pattern to define an implicit conversion from any object into a class that can do a kind of partial matching:
class PartialMatcher[A](a: A) {
def partialMatch(f: PartialFunction[A, Unit]): Unit = if (f.isDefinedAt(a)) f(a)
}
implicit def makePartialMatcher[A](a: A) = new PartialMatcher(a)
Then just replace all of those matches with partialMatch:
def findAll(cfg: Cfg, consumer: Consumer[Violation]): Unit = {
val fa = new FlowAnalyzer
val states = fa.analyze(cfg)
states.foreach { case (cfe, state) => cfe partialMatch {
case assign: Assignment => assign.getRight partialMatch {
case expression: BinaryExpression => expression.getOperator partialMatch {
case Operator.Div | Operator.Rem => processDivisions()
}
}
}}
}
Note that there are other reasons why you might avoid this kind of thing... overusing implicit conversions can make understanding code a lot more difficult. It's a stylistic choice.
Use .collect:
def findAll(cfg: Cfg, consumer: Consumer[Violation]): Unit = {
val fa = new FlowAnalyzer
val states = fa.analyze(cfg)
states.collect { case (assign: Assignment, _) =>
assign.getRight
}.collect { case expression: BinaryExpression =>
expression.getOperator
}.collect { case Operator.Div | Operator.Rem =>
processDivisions
}

in scala why does for yield return option instead of string

I'm new to scala I'm trying to understand for/yield and don't understand why the following code returns an option not a String
val opString: Option[String] = Option("test")
val optionStr : Option[String] = for {
op <- opString
} yield {
opString match {
case Some(s) => s
case _ => "error"
}
}
A for-expression is syntactic sugar for a series of map, flatMap and withFilter calls. Your specific for-expression is translated to something like this:
opString.map(op => opString match {
case Some(s) => s
case _ => "error"
})
As you can see, your expression will just map over opString and not unwrap it in any way.
Desugared expression for your for ... yield expression is:
val optionStr = opString.map {
op =>
opString match {
case Some(s) => s
case _ => "error"
}
}
The type of opString match {...} is String, so the result type of applying map (String => String) to Option[String] is Option[String]
What you're looking for is getOrElse:
opString.getOrElse("error")
This is equivalent to:
opString match {
case Some(s) => s
case _ => "error"
}

Applying or operation to Option results

I have the following code:
class CSplit(var s1: CanvNode, var s2: CanvNode) extends SplitPane
{
topComponent = s1.merge
bottomComponent = s2.merge
def containsV(orig: MapCanvT): Option[MapCanvT] =
{
def containsIn(cn: CanvNode): Option[MapCanvT] = cn match
{
case Left => None
case Right(mc) => if (mc == orig) Some(mc) else None
}
containsIn(s1) match
{
case Some(mc) => Some(mc)
case None => containsIn(s2)
}
}
}
I want to reduce the code of the containsV method. My first thought was to use a fold method to shorten the containsIn method. But Option doesn't have one, nor does it extend Class Either. Shouldn't Option[T] extend Either[T, None] ? Then at least one could use Either's fold method.
My final thought was to treat s1 and s2 as a List and do find over it but I can't get this to compile:
def containsV(orig: MapCanvT):
Option[MapCanvT] = ::[CanvNode](s1, s2).find(_ == Right(orig))
Scala 2.10 adds fold to Option. In the meantime you can use map(f).getOrElse(g) instead:
// These produce identical results
o.fold(g)(x => f(x))
o.map(x => f(x)).getOrElse(g)
Edit: so, for example, the following three do the same thing:
val os: List[Option[Int]] = List(Some(5),None)
// Explicit match
os.map{ _ match {
case Some(x) => x+3
case None => 0
}}
// map+getOrElse
os.map{ _.map(_+3).getOrElse(0) }
// fold
os.map{ _.fold(0)(_+3) }
In the fold case, you give the default value for the None case first, and then the function that handles the case where there is a value. In each case you should get List(8,0).
It can be implemented with a list by using the collectFirst method
def containsV(orig: MapCanvT): Option[MapCanvT]
= List(s1, s2).collectFirst {case i: MapCanvT if (i == (orig) => i}
Let's start with the easy part:
containsIn(s1) match
{
case Some(mc) => Some(mc)
case None => containsIn(s2)
}
is the same as
containsIn(s1) orElse containsIn(s2)
Now we only have to deal with containsIn:
def containsIn(cn: CanvNode): Option[MapCanvT] = cn match
{
case Left => None
case Right(mc) => if (mc == orig) Some(mc) else None
}
We can use fold on Either, which gets rid of most of the pattern matching:
cn.fold(_ => None, Some(_))
But there's the orig thingy. We can handle it with a filter, though:
cn.fold(_ => None, Some(_)) filter (orig.==)
Thus:
def containsV(orig: MapCanvT): Option[MapCanvT] = {
def containsIn(cn: CanvNode): Option[MapCanvT] =
cn.fold(_ => None, Some(_)) filter (orig.==)
containsIn(s1) orElse containsIn(s2)
}
I think orElse is much overlooked.

Optional function parameter with generic return type

How would you implement class that parses some input via regex and transforms founded string to some other type? My approach is:
class ARegex[T](regex:Regex, reform:Option[String => T]){
def findFirst(input:String):Option[T] = {
(regex.findFirstIn(input), reform) match{
case (None, _) => None
case (Some(s), None) => Some(s) // this won't compile because of type mismatch
case (Some(s), Some(fun)) => Some(fun(s))
}
}
}
class BRegex[T](regex:Regex, reform:Option[String => T]) {
def findFirst(input:String) = { //returns Option[Any] - erasure
(regex.findFirstIn(input), reform) match{
case (None, _) => None
case (Some(s), None) => Some(s)
case (Some(s), Some(fun)) => Some(fun(s))
}
}
}
We can solve this problem by eliminating the Option part of the reform's type, and using a different mechanism to indicate that we don't want to change the match in any way. This mechanism is to use identity as a default parameter or pass identity when you don't want the type to change.
class ARegex[T](regex:Regex, reform:String => T = identity[String](_)){
def findFirst(input:String):Option[T] = {
regex.findFirstIn(input) match{
case None => None
case Some(s) => Some(reform(s))
}
}
}
new ARegex("something".r).findFirst("something else") //returns Option[String]
new ARegex("3".r, {x=>x.toInt}).findFirst("number 3") //returns Option[Int]
Well, the problem is the type mismatch, because you are returning either a String or a T, which, of course, are unified at Any. You can't say you are going to return Option[T] and then return Option[String].
Other than that, a simplified version of that code is this:
class ARegex[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[Any] =
regex findFirstIn input map { s => reform map (_(s)) getOrElse s }
}
You could return an Option[Either[String, T]], though. The code would look like this:
class ARegex[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[Either[String, T]] =
regex findFirstIn input map { s => reform map (_(s)) toRight s }
}
Why is reform Option[String => T] instead of just String => T? If you don't pass in a mechanism for creating an instance of your desired type, there's no mechanism for the runtime system to actually create the appropriate object. If you really need to pass in an Option[String => T] then your second case should simply return None.
Also, flatMap is your friend, and will give you the correct behavior (i.e. if reform is None, the method returns None.
class RegexExtractor[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[T] = reform.flatMap(f => regex.findFirstIn(input).map(f))
}