Replace if-else with functional code

I know that in a functional style, all if-else blocks are replaced with a pattern match. But how can I handle Map matching patterns in Scala? For example, how can I rewrite this code in a more functional style?

  val myMap= getMap() if(myMap.contains(x) && myMap.contains(y)) Some(myMap(x) + myMap(y)) else if(myMap.contains(x + y)){ val z = myMap(x + y) if (z % 2 == 0) Some(z) else None } else None 
+6
source share
4 answers

Using if-else is perfectly acceptable for functional programming, because if-else in Scala is just an expression. Reasons to choose between if-else and pattern matching should focus primarily on improving readability.

Here I am trying to rewrite the code. In fact, I do not use pattern matching, but the for understanding is to summarize the values.

 def sumOfValues = for{ mx <- myMap.get(x) my <- myMap.get(y) } yield mx + my def valueOfSumIfEven = myMap.get(x+y).filter(_ % 2 == 0) sumOfValues orElse valueOfSumIfEven 
+18
source

To answer your question directly - you can filter cases using additional if:

 getMap match { case myMap if (myMap.contains(x) && myMap.contains(y)) => Some(myMap(x) + myMap(y)) case myMap if (myMap.contains(x+y)) => myMap(x+y) match { case z if (z % 2 == 0) => Some(z) case _ => None } case _ => None } 

([edit: there really is] Although Scala has โ€œelse-ifโ€), this is actually a way to do if-else-if-else (looking at the generated class files, this is what it actually does, whereas if -else is equivalent to triple ?: in java, returning Unit implicitly when the final other is missing).

+2
source

What about:

 myMap.get(x) .zip(myMap.get(y)) .headOption.map(x => x._1 + x._2) .orElse(myMap.get(x + y) .filter(__ % 2 == 0)) 
+2
source

Well, you can write your test as follows:

 myMap.get(x).flatMap(xVal => myMap.get(y).map(_ + xVal)) .orElse(myMap.get(x+y).filter(_ % 2 == 0)) 

But what you already know may be clearer for everyone who is trying to understand the intention. Please note that the first line (from flatMap to the end) can also be written as for understanding, as shown in @ziggystar's answer).

Perhaps the modular test part could be rewritten as a match if it looks cleaner:

 if(myMap.contains(x) && myMap.contains(y)) Some(myMap(x) + myMap(y)) else myMap.get(x + y) match { case Some(z) if (z % 2 == 0) => Some(z) case _ => None } 
+1
source

Source: https://habr.com/ru/post/952014/


All Articles