scala: convert match statement to pattern matching anonymous function - with values - scala

like similar question: Convert match statement to partial function when foreach is used. Now similarly, IntelliJ asks me to improve my code. The difference is, that I use values for the matching:
val matchMe = "Foo"
keys.foreach(key =>
key match {
case `matchMe` => somethingSpecial()
case _ => somethingNormal(key, calcWith(key))
})
Refactoring this to a anonymous pattern-matching function would look something like:
keys.foreach {
case `matchMe` => somethingSpecial(_)
case _ => somethingNormal(_, calcWith(_)) //this doesn't work
}
Note that in the second case, I cannot use _ since I need it twice. Is there some way to use an anonymous pattern-matching function here?

You can't use the wildcard _ here, its purpose is to indicate you don't care about the value you're matching against.
You can use a named parameter :
keys.foreach {
case `matchMe` => somethingSpecial(matchMe)
case nonSpecialKey => somethingNormal(nonSpecialKey, calcWith(nonSpecialKey))
}
Without any restrictions placed on it, it will match any value. Do note that the order of cases is important, as case x => ... match anything and will essentially shortcut other case statements.
As an aside, I don't think your somethingSpecial(_) does what you want/expect it to. It's only a short version of x => somethingSpecial(x), not somethingSpecial(matchMe).

Related

How to check if function is partial in Scala?

I have a method that receives a function, but that function may be partial, in such case I don't want it to fail with MatchError.
def doSomething[X,Y](opt:Option[X])(f:X=>Y)={
f match {
case p:PartialFunction[X,Y]=> opt.flatMap(p.lift) //This doesn't seem to work
case _ => opt.map(f)
}
}
That way I can use the method like this
doSomething(x){
case t if predicate(t) => otherMethod(t)
}
so in case I don't have a predicate, I can use it like
this doSomething(x)(otherMethod) instead of
doSoemthing(x){
case t=> otherMethod(t)
}
Note: Looking for a solution that doesn't require catching MatchError exceptions
This isn't an answer because I don't think that what you want is possible in Scala.
The original method is fine and works as expected, though it could be a bit simpler:
def doSomething[X, Y](opt: Option[X])(f: X => Y): Option[Y] = {
f match {
case p: PartialFunction[X, Y] => opt.collect(p)
case _ => opt.map(f)
}
}
The problem is here:
doSomething(x){
case t if predicate(t) => otherMethod(t)
}
Scala is creating a Function rather than a PartialFunction from that match expression so the test is failing. If you pass a real PartialFunction the method works OK.
val p: PartialFunction[Int, Int] = {
case i: Int if i > 0 => i
}
doSomething(Some(0))(p) // Returns None
I don't think there is any way of doing what you want, mainly because doSomething has multiple argument lists which messes up type deduction for the second argument list.
My suggestion is just to use
x.map(f)
or
x.collect{
case ...
}
as appropriate in the calling code.
The syntax for partial function has been changed since 2.9 per SLS 8.5, so that even you do { case x => y}, it DOES NOT mean it is a partial function. Its type will be exact as you define it as.
In your case, you defined it as X=>Y (as in your function parameter), so it is just a X=>Y (it got compiled into a regular function, and non match cases will throw MatchError), and even you do isInstanceOf[PartialFunciton[_,_]], it won't match.
To make your scenario work, you can just simply cast the passed function as PartialFunction, like:
doSomething(Some(1))({case 2 => 0}: PartialFunction[Int,Int]) //This returns None without MatchError
while
doSomething(Some(1)){case 2 => 0} //This gives MatchError and it is not recognized as PartialFunction inside the body
This is probably not as convenient as you thought it is, but it is the only way to make it work. (or you define 2 separate functions for either case, like collect and map in standard library)
I'm not sure what you are passing as a Partial Function, but definitely you should have to define it with specific signature like this:
val positive: PartialFunction[Int, Option[Int]] = {
case x if x >= 0 => Some(x)
case _ => None
The positive function is defined only for positive numbers. In case of negative numbers, the function returns None and you won't get scala.MatchError in runtime.
This specific function enables you to access to isDefinedAt method which is testing dynamically if a value is in the domain of the function.
postive(5).isDefinedAt // true
poistive.isInstanceOf[PartialFunction[Int, Option[Int]]] // true
I demonstrated here why you are always getting false when you check p.isInstanceOf
def doSomething[X,Y](opt:Option[X])(f:X=>Y)={
f match {
case p if p.isInstanceOf[PartialFunction[X,Y]] =>
println("I'm a pf")
println(s"Is it PartialFunction: ${p.isInstanceOf[PartialFunction[X,Y]]}")
opt.map(p)
case _ =>
println("I'm not a pf")
opt.map(f)
}
}
doSomething[Int, Option[Int]](Some(5))(positive) // partial function case
doSomething[Int, String](Some(5)) { // tricky case
case s => s.toString
}
You can play with it here:

scala match expression avoiding code duplication

Say I am using a match expression to test a value that may or may not be in a Map object as follows:
map.get(key) match {
case Some(value) if (cond1(value)) => res1(value)
case Some(value) if (cond2(value)) => res2()
case None => res2()
case _ => // None of the above
}
As you can see I want to call the res2 in either case where I have a value for my key and it meets condition 2 or I have no value for key. Can anyone suggest a better construct that would avoid the duplicate calls to res2() in the sample above?
Thanks
Des
* Sorry I realised that the code sample was not quite correct and have updated accordingly. I only want to call res2 in the case where the value for the key meets cond2 OR there is NO entry for key.
I believe what you want is:
map.get(key) match {
case Some(value) if (cond1(value)) => res1(value)
case o: Option[String] if ( o.forall(cond2) ) => res2()
case _ =>
}
replacing [String] with whatever the type of key is.
The names of the methods on Option aren't always the most obvious; in maintaining functional purity they sacrifice clarity for us illiterati. In this case, the scaladoc for Option tells us that forall:
Returns true if this option is empty or the predicate p returns true
when applied to this scala.Option's value.
Without gard if that are only possibilities:
case Some(value) => if (cond1(value) ) res1(value) else res2()

Use same variable multiple times within one pattern

I'd like to be able to use a single variable multiple times within one pattern, so that it will only match if the same value is present in all places, such as
list match {
case x :: x :: xs => // recurse
}
which would match List(1,1,2) but would not match List(1,2,1). But this does not compile with error: x is already defined as value x.
In researching this question, I found out that I can also include a guard in the case clause, so I can do
list match {
case x1 :: x2 :: xs if x1==x2 => // recurse
}
which seems to work the same way (it does, right?). This is good, but it wouldn't look as clean if I wanted the same value in many places, like
list match {
case x1::x2::x3::x4::xs if x1==x2 && x2==x3 && x3==x4 => // recurse
}
Is there any more elegant way I can do this?
A few notes: Yes, I am just learning scala, if that wasn't clear, so I'm not sure this is something I'd ever really want to do, but I'm just interested in what's possible. In that regard, I'm not really looking for a completely different solution, like takeWhile or filter or something, but more so am specifically interested in pattern matching.
Scala doesn't provide quite that much flexibility with its matches (which may be a good thing, as one has to be aware of errors arising from unintentional variable re-use).
If you have a large number of identical items, you might want to consider a nested match (but note that you won't fail out of the inner match to be completed later down the outer match, so you have to handle everything locally):
list match {
case x :: rest => rest match {
case `x` :: `x` :: `x` :: xs => println("Four of the same")
case _ => println("Well, nonempty at least")
}
case _ => println("Boring, there's nothing here!")
}
Note the backticks which mean "we've already got this variable, check against it, don't set it!".
Alternatively, if you have specialized functionality that you use repeatedly, you can create a custom matcher:
object FourOf {
def unapplySeq(xs: List[Int]): Option[(Int, List[Int])] = xs match {
case x :: y :: z :: a :: rest if x==y && y==z && z==a => Some((x,rest))
case _ => None
}
}
and then use it whenever you need that complicated pattern:
list match {
case FourOf(x,rest) => println("four of the same")
case x :: more => println("Nonempty")
case _ => println("Yawn")
}
Neither of these are quite as tidy and flexible as what you were apparently hoping for, but then again, I'm not sure flipping between assigning and testing the same variable in a match statement is a good way to write clear code anyway.
For many repeats you might use stable identifiers to do a comparison (instead of catching a value):
val x = list.head
list match {
case `x`::`x`::`x`::`x`::xs => ....
}
But note that this won't work on empty list (you just cannot get head of it).
I think Rex's answer rocks. I am a fan of unapplySeq. But here's a not-so-clever-and-maybe-wasteful alternative, if your main bother is just with the sequence of =='s in each guard.
So in the TMTOWTDI spirit:
def same[A](xs: A*) = xs forall (xs.head==)
// Then in your pattern match,
list match {
// case x1::x2::x3::x4::xs if x1==x2 && x2==x3 && x3==x4 => // recurse
case x1::x2::x3::x4::xs if same(x1,x2,x3,x4) => // recurse
}
I like Om's answer as well, so here's an adaptation:
list.headOption map (x => list match {
case `x`::`x`::`x`::`x`::xs => //...;
case _ => // ...
}) getOrElse {
// do what you'd have done for an empty list...
}

Matching on tuple using comparison operator

I would like to match on tuple pattern, but I can not find any solution how to match using comparison operators. My code is:
myTuple match {
case (-1,-1,true) => ...
case (_>=0,-1,_) => ...
}
This gives give compile time error.
I also tried to use if guard, but as I see it can not be applied this way:
case (_ if _>=0,-1,_) => ...
Is my approach correct or should I solve this on an different way?
Thanks
Zoltan
The syntax is wrong, you should use guard as follows:
myTuple match {
case (-1,-1,true) => ...
case (x,-1,_) if x >= 0 => ...
case _ => ... // default
}
There are a lot of good introduction to scala pattern matching on the web. Here is the first detailed one, I've found on google: Playing with Scala's pattern matching

Processing Scala Option[T]

I have a Scala Option[T]. If the value is Some(x) I want to process it with a a process that does not return a value (Unit), but if it is None, I want to print an error.
I can use the following code to do this, but I understand that the more idiomatic way is to treat the Option[T] as a sequence and use map, foreach, etc. How do I do this?
opt match {
case Some(x) => // process x with no return value, e.g. write x to a file
case None => // print error message
}
I think explicit pattern matching suits your use case best.
Scala's Option is, sadly, missing a method to do exactly this. I add one:
class OptionWrapper[A](o: Option[A]) {
def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default)
}
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o)
which has the slightly nicer (in my view) usage
op.fold{ println("Empty!") }{ x => doStuffWith(x) }
You can see from how it's defined that map/getOrElse can be used instead of pattern matching.
Alternatively, Either already has a fold method. So you can
op.toRight(()).fold{ _ => println("Empty!") }{ x => doStuffWith(x) }
but this is a little clumsy given that you have to provide the left value (here (), i.e. Unit) and then define a function on that, rather than just stating what you want to happen on None.
The pattern match isn't bad either, especially for longer blocks of code. For short ones, the overhead of the match starts getting in the way of the point. For example:
op.fold{ printError }{ saveUserInput }
has a lot less syntactic overhead than
op match {
case Some(x) => saveUserInput(x)
case None => printError
}
and therefore, once you expect it, is a lot easier to comprehend.
I'd recommend to simply and safely use opt.get which itself throws a NoSuchElementException exception if opt is None. Or if you want to throw your own exception, you can do this:
val x = opt.getOrElse(throw new Exception("Your error message"))
// x is of type T
as #missingfaktor says, you are in the exact scenario where pattern matching is giving the most readable results.
If Option has a value you want to do something, if not you want to do something else.
While there are various ways to use map and other functional constructs on Option types, they are generally useful when:
you want to use the Some case and ignore the None case e.g. in your case
opt.map(writeToFile(_)) //(...if None just do nothing)
or you want to chain the operations on more than one option and give a result only when all of them are Some. For instance, one way of doing this is:
val concatThreeOptions =
for {
n1 <- opt1
n2 <- opt2
n3 <- opt3
} yield n1 + n2 + n3 // this will be None if any of the three is None
// we will either write them all to a file or none of them
but none of these seem to be your case
Pattern matching is the best choice here.
However, if you want to treat Option as a sequence and to map over it, you can do it, because Unit is a value:
opt map { v =>
println(v) // process v (result type is Unit)
} getOrElse {
println("error")
}
By the way, printing an error is some kind of "anti-pattern", so it's better to throw an exception anyway:
opt.getOrElse(throw new SomeException)