Scala: simplify case with comparison - scala

Let's say, I have the following code snippet:
val num = Future.successful(10)
num map {
case n if n > 0 => // do something
case _ // do something
}
My question is: can I simplify case n if n > 0 somehow?
I expected that I can write something like:
case _ > 0 => // do something
or with explicitly specified type (although we know that Future has inferred type [Int]):
case _: Int > 0 => // do something
Can this code be simplified somehow?

You can't simplify case n if n > 0 => ....
Every case clause in a pattern match needs to have a pattern and (optionally) a guard.
The syntax you are referring to (_ > 0) is only valid in lambdas, but there's no similar special syntax for case clauses.

If you want to simplify the guard, you can filter the Future a priori:
val num = Future.successful(10).filter(_ > 0).map { nat =>
}
Otherwise, you can keep the guard and use Future.collect:
val num = Future.successful(10).collect {
case n if n > 0 => // do something
}
One important thing to note is that if the partial function is not defined for the value which returned (i.e for your case -1) then the resulting future will be a Failure containing a NoSuchElementException.
Other than these options, you'll need the guard. I don't see any syntactically shorter way to express it.

Related

Scala Match Case structure and traversing a List with odd terms cs and m?

I am trying to understand this piece of code here
def countChange(money: Int, coins: List[Int]): Int = (money, coins) match {
case (0, _) => 1
case (m, _) if m < 0 => 0
case (_, cs) if cs.isEmpty => 0
case (m, cs) => countChange(m - cs.head, cs) + countChange(m, cs.tail)
}
}
where I cannot understand the pairs (0,_), (m,_), (_,cs) and (m,cs) because the terms m and cs are undefined in the body of the code.
What is this construction in traversing the List called? A pair of some matching patterns?
The list is being traversed recursively. This construct is called pattern matching
You can read it like:
If the tuple (money, coins) is a tuple whose first value is 0 then return 1 ignore the second value of the tuple
If the tuple (money, coins) is a tuple has a first value below 0 then return 0 ignore the second value of the tuple.
And so on...
The _ is used in pattern matching to simbolize that we don't care what that parameter is, it can be anything
Pattern matching in Scala is backed by the unapply method of Objects, read more about extractors. Meaning that for each case the method unapply will be called with the tuple (money, coins) as argument and if determines that it is a match it will pass the respective first value and second value to the case clauses.
Example:
The statement case (m, _) => ... will lead to the call Tuple2.unapply((money, coins))
Note
Case classes already define unapply methods for us. That's why you can use them in pattern matching 'out of the box'. Tuple2 is a case class.
This is an example of pattern matching, which is being used to recursively traverse your list of coins. Here is the same code re-written with comments, the important thing to know is that each case statement is matching a possible pattern of the tuple, and the _ are used for ignoring pieces of the tuple.
def countChange(money: Int, coins: List[Int]): Int = {
// Construct a tuple for pattern matching on
val tuple: (Int, List[Int]) = (money, coins)
tuple match {
// Check to see if money == 0
case (0, _) => 1
// m represents money, use a guard to check if m is negative
case (m, _) if m < 0 => 0
// cs represents coins, use a guard statement check for empty list
case (_, cs) if cs.isEmpty => 0
// Recursive step. Since the patterns are tried in order, we
// now know that if we make it to here m (money) is non-zero
// and non-negative, and we know that cs (coins) is a non-empty
// list. Now we can call the recursive function safely on
// the head of the list
case (m, cs) => countChange(m - cs.head, cs) + countChange(m, cs.tail)
}
}
This construct is often used to match on more than one variable at the same time. At the top of the match, you see (money, coins). This means that it's matching on the pair of both money and coins. It doesn't have a name, because it's perfectly ordinary matching on two values simultaneously.
I cannot understand the pairs (0,_), (m,_), (_,cs) and (m,cs) because the terms m and cs are undefined in the body of the code.
These terms are defined in the code. The cases define them. That's what matching and destructuring is all about.
(money, coins) match {
case (0, _) => 1 // If money == 0, then coins is ignored and we return 1
case (m, _) if m < 0 => 0 // m = money, coins is ignored. If m < 0, return 0
case (_, cs) if cs.isEmpty => 0 // money is ignored, cs = coins.
// If we have no coins, return 0.
case (m, cs) => countChange(m - cs.head, cs) + countChange(m, cs.tail)
// Otherwise, m = money, cs = coins. Recurse down the list with
// countChange(money - coins.head, coins) + countChange(money, coins.tail)
}
The reason for the tupling (money, coins) is because these patterns depend on both money and coins. You'd either need to nest matchs (ugly) or do even more ugly boolean logic in order to replicate these semantics.

disjoint Pattern-Matching

i have a question about disjoint Matching pattern. The matching pattern is disjoint when each case does not step on other cases.
def func(list: List[Int]): Int = list match {
case Nil => 0
case x::t if (x < func(t)) => x
case x::t => func(t)
}
My question: is "if" statement also counted to check if these cases disjoint is?
so if we have a patching pattern like this it means the last case also include the second case and it would not be disjoint anyway . But if i change the last case to
case x::t if (x >= func(t)) => func(t)
would the matching pattern considered disjoint ?
Since x < func(t) = !(x >= func(t)), yes, these patterns are all disjoint. The compiler doesn't use predicate disjointness in anyway; this will have no concrete implications.

Scala pattern matching with tuple: matching equal values in the tuple

I have created a function to retrieve a given value from the Pascal Triangle and I've used if statements. Now I want to refactor the function to use pattern matching.
My if based function looks like this:
def valueAt(row: Int, column: Int): Int = {
// ...
else if (row == column) 1 // last column
//
}
My second version of this function, using pattern matching has the following signature:
def valueAt2(row: Int, column: Int): Int = (row, column) match {
// ...
}
Is it possible to define a case for when the row and column have the same value?
I have tried using the same variable name in the case, like this:
case (x, x) => 1 // last column
And I have also tried to use the value of the row in the column, like this:
case (_, row) => 1 // last column
But they don't work. In the first case I have a compilation error and in the second the IDE says that I'm shadowing the variable row from the match.
It this possible?
Thanks.
For the first one, use an if guard:
(1, 2) match { case (x, y) if x == y => 1; ... }
For the second one, when you want to match a variable (instead of binding and shadowing it), you can use backticks (`):
(1, 2) match { case (_, `row`) => 1; ... }
You can use a guard, which is a part of a case expression that can check non-stable conditions, and not surprisingly resembles an if statement:
(row, column) match {
case (x, y) if x == y => 1
// other cases...
}
Note that inputs not matching this guard (i.e. for which x != y) would continue to check the other cases, so, for example, another case case (x, y) => ... can follow, and assume x != y.

Implementing NPlusK patterns in Scala

I thought I could implement n+k patterns as an active pattern in scala via unapply, but it seems to fail with unspecified value parameter: k
object NPlusK {
def apply(n : Int, k : Int) = {
n + k
}
def unapply(n : Int, k : Int) = {
if (n > 0 && n > k) Some(n - k) else None
}
}
object Main {
def main(args: Array[String]): Unit = {
}
def fac(n: Int) : BigInt = {
n match {
case 0 => 1
case NPlusK(n, 1) => n * fac(n - 1)
}
}
}
Is it possible to implement n+k patterns in Scala and in that event how?
You should look at this question for a longer discussion, but here's a short adaptation for your specific case.
An unapply method can only take one argument, and must decide from that argument how to split it into two parts. Since there are multiple ways to divide some integer x into n and k such that x = n + k, you can't use an unapply for this.
You can get around it by creating a separate extractors for each k. Thus, instead of NplusK you'd have Nplus1, Nplus2, etc since there is exactly one way to get n from x such that x = n + 1.
case class NplusK(k: Int) {
def unapply(n: Int) = if (n > 0 && n > k) Some(n - k) else None
}
val Nplus1 = NplusK(1)
val Nplus1(n) = 5 // n = 4
So your match becomes:
n match {
case 0 => 1
case Nplus1(n) => n * fac(n - 1)
}
Deconstructor unapply does not work this way at all. It takes only one argument, the matched value, and returns an option on a tuple, with as many elements as there are arguments to the your pattern (NPlusK). That is, when you have
(n: Int) match {
...
case NPlusK(n, 1)
It will look for an unapply method with an Int (or supertype) argument. If there is such a method, and if the return type is a Tuple2 (as NPlusK appears with two arguments in the pattern), then it will try to match. Whatever subpattern there are inside NPlusK (here the variable n, and the constant 1), will not be passed to unapply in anyway (what do you expect if you write case NPlusK(NPlusK(1, x), NPlusK(1, y))?). Instead, if unapply returns some tuple, then each element of the tuple will be matched to the corresponding subpattern, here n which always matches, and 1 which will match if the value is equal to 1.
You could write
def unapply(n: Int) = if (n > 0) Some((n-1, 1)) else None.
That would match when your NPlusK(n, 1). But that would not match NPlusK(n, 2), nor NPlusK(1, n) (except if n is 2). This does not make much sense. A pattern should probably have only one possible match. NPlusK(x, y) can match n in many different ways.
What would work would be something Peano integers like, with Succ(n) matching n+1.

A way to write this more concise? Need to check if a number is under 0

val total_breaks = //a random number
total_breaks match {
case i if(i < 0) => chartTemplate.setAttribute("totalBreaks", 0)
case _ => chartTemplate.setAttribute("totalBreaks", total_breaks)
}
I was thinking there was a function in Scala that could shorten this. I thought min did this but I guess not. I can't seem to find documentation on min, max, etc.
Something like total_breaks.min(0). Display 0 if under 0 if not display total_breaks.
Also is there a way do something like this
(4 + 5) match {
case 0 => println("test")
case _ => println(_) //i need to display the number passed into match? Is this not possible?
}
If I do case i => println(i) is that the same as case _ => ? Is that the fallback?
There are methods min and max defined in GenTraversableOnce, and thus available on sequences. You can use them as:
scala> List(1, -4, 0).min
resN: -4
There is also min and max defined in RichInt, that work like operators on anything that can be converted to RichInt, typically your vanilla integers:
scala> -4 min 0
resN: -4
So if you want something that returns your number, say x if x is greater than 0 and 0 otherwise, you can write:
scala> x max 0
That means you can rewrite your pattern-matching as:
chartTemplate.setAttribute("totalBreaks", total_breaks max 0)
For your second question, _ and i are both valid patterns that will match anything. The difference is that in the first case you do not bind what you have matched to a variable. Using println(_) is wrong, though; as such, it corresponds to an anonymous function that prints its first argument. So if you don't want to repeat the expression (4 + 5), you should indeed write your pattern and code as:
case i => println(i)