Scala how to avoid var during some override condition - scala

Functional programming style of coding guideline says we should not use null or var in Scala for better functional programming code.
I want to perform some operation like below
var a = 2
if(condition==true){
a = a * 3 /*someOperation*/
}
if(condition2==true){
a = a * 6 /*someOperation*/
}
if(condition3==true){
a = a * 8 /*someOperation*/
}
val b = a * 2/*someOperation*/
So now how to avoid var in this condition and replace it with val?

The simplest way to avoid var with multiple conditions is to use temporary values
val a1 = 2
val a2 = if (condition) a1*3 else a1
val a3 = if (condition2) a2*6 else a2
val a = if (condition3) a3*8 else a3
val b = a * 2/*someOperation*/
In the real code you would give a1, a2, and a3 meaningful names to describe the result of each stage of processing.
If you are bothered about having these extra values in scope, put it in a block:
val a = {
val a1 = 2
val a2 = if (condition) a1*3 else a1
val a3 = if (condition2) a2*6 else a2
if (condition3) a3*8 else a3
}
Update
If you want a more functional approach, collect the conditions and modifications together and apply them in turn, like this:
val mods: List[(Boolean, Int=>Int)] = List(
(condition, _*3),
(condition2, _*6),
(condition3, _*8)
)
val a = mods.foldLeft(2){ case (a,(cond, mod)) => if (cond) mod(a) else a }
This is really only appropriate when either the conditions or the modifications are more complex, and keeping them together makes the code clearer.

val a = 2 * (if (condition) 3 else 1)
val b = 2 * a
Or, perhaps...
val a = 2
val b = 2 * (if (condition) a*3 else a)
It depends on if/how a is used after these operations.

I think you might have oversimplified your example, because we know the value of a when writing the code so you could just write it out like this:
val a = if (condition) 2 else 6
val b = a * 2
Assuming your real operation is more complex and can't be precalculated like that, then you might find a pattern match like this is a nicer way to do it:
val a = (condition, 2) match {
case (true, z) =>
z * 3
case (false, z) =>
z
}
val b = a * 2

You can try the following approach:
type Modification = Int => Int
type ModificationNo = Int
type Conditions = Map[ModificationNo, Boolean]
val modifications: List[(Modification, ModificationNo)] =
List[Modification](
a => a * 3,
a => a * 6,
a => a * 8
).zipWithIndex
def applyModifications(initial: Int, conditions: Conditions): Int =
modifications.foldLeft[Int](initial) {
case (currentA, (modificationFunc, modificationNo)) =>
if (conditions(modificationNo)) modificationFunc(currentA)
else currentA
}
val a: Int = applyModifications(initial = 2,
conditions = Map(0 -> true, 1 -> false, 2 -> true))
It may look complicated but this approach allows additional flexibility if number of conditions is big enough.
Now when you have to add more conditions, you don't need to write new if-statements and further reassignments to var. Just add a modification function to an existing list of

there is no 1 perfect solution.
sometimes it is ok to use var if it simplifies the code and limited in scope of a single function.
that being said, this is how I would do it in functional way:
val op1: Int => Int =
if (condition1) x => x * 3
else identity
val op2: Int => Int =
if (condition2) x => x * 6
else identity
val op3: Int => Int =
if (condition3) x => x * 8
else identity
val op = op1 andThen op2 andThen op3
// can also be written as
// val op = Seq(op1, op2, op3).reduceLeft(_ andThen _)
val a = 2
val b = op(a) * 2

The easiest way it to wrap your variable into a monad, so that you .map over it. The simplest monad is an Option, so you could write:
val result = Option(a).map {
case a if condition => a*2
case a => a
}.map {
case a if condition2 => a*6
case a => a
}.fold(a) {
case a if condition3 => a*8
case a => a
}
(The last operation is fold instead of map so that you end up with the "raw" value for the result, rather than an option. Equivalently, you could write it as a .map, and then add .getOrElse(a) at the end).
When you have many conditional operations like this, or many use cases where you have to repeat the pattern, it might help to put them into a list, and then traverse that list instead:
def applyConditionals[T](toApply: (() => Boolean, T => T)*) = toApply
.foldLeft(a) {
case (a, (cond, oper)) if cond() => oper(a)
case (a, _) => a
}
val result = applyConditionals[Int] (
(() => condition, _ * 2),
(() => condition2, _ * 6),
(() => condition3, _ * 8)
)

The important point is that FP is a whole new paradigm of programming. Its so fundamentally different that sometimes you can not take an excerpt of imperative code and try to convert it to functional code.
The difference applies not just to code but to the way of thinking towards solving a problem. Functional programming requires you to think in terms of chained mathematical computation which are more or less independent of each other (which means that each of these mathematical computation should not be changing anything outside of its own environment).
Functional programming totally avoids mutation of state. So, if your solution has a requirement to have a variable x which has a value 10 at one point and other value 100 at some other point... then your solution is not functional. And you can not write function code for a solution which is not functional.
Now, if you look at your case (assuming you do not actually need a to be 2 and then change to 6 after sometime) and try to convert it into chain of independent mathematical computation, then the simplest one is following,
val a = if (condition) 2 else 6
val b = a * 2

Related

Scala apply list of functions to a object

I have a lit of functions
val f1 = (x: Int) => x + 1
val f2 = (x: Int) => x + 2
val f3 = (x: Int) => x + 3
I have a single value:
val data = 5
I want to apply all the functions to the value and return single value. So
f3(f2(f1(data)))
And must return 11.
Now, if I have a seq of functions:
val funcs = Seq(f1, f2, f3)
How can I get 11 from applying all the functions to the data variable ? What is the scala-way to do that ?
yet another way to doing it using chain method in the Function helper object
Function.chain(funcs)(data)
What you are looking for is foldLeft. Indeed, for each function, you apply it to the previous result:
funcs.foldLeft(data){ (previousres, f) => f(previousres) }
you can use foldLeft:
val result = funcs.foldLeft(5)((acc,curr) => curr(acc) )
Basically, you are trying to achieve Function Composition here. So, you could use compose and andThen methods here as:
val data = 5
val funcs = Seq(f1, f2, f3)
//using compose
val result1 = funcs.reduce((a,b) => a.compose(b))(data)
//using andThen
val result2 = funcs.reduce((a,b) => a.andThen(b))(data)
Both result1 and result2 will be 11 in your example.
Please note that the way andThen and compose operate are different. You could see Functional Composition for more information.

Scala: Best way to filter & map in one iteration

I'm new to Scala and trying to figure out the best way to filter & map a collection. Here's a toy example to explain my problem.
Approach 1: This is pretty bad since I'm iterating through the list twice and calculating the same value in each iteration.
val N = 5
val nums = 0 until 10
val sqNumsLargerThanN = nums filter { x: Int => (x * x) > N } map { x: Int => (x * x).toString }
Approach 2: This is slightly better but I still need to calculate (x * x) twice.
val N = 5
val nums = 0 until 10
val sqNumsLargerThanN = nums collect { case x: Int if (x * x) > N => (x * x).toString }
So, is it possible to calculate this without iterating through the collection twice and avoid repeating the same calculations?
Could use a foldRight
nums.foldRight(List.empty[Int]) {
case (i, is) =>
val s = i * i
if (s > N) s :: is else is
}
A foldLeft would also achieve a similar goal, but the resulting list would be in reverse order (due to the associativity of foldLeft.
Alternatively if you'd like to play with Scalaz
import scalaz.std.list._
import scalaz.syntax.foldable._
nums.foldMap { i =>
val s = i * i
if (s > N) List(s) else List()
}
The typical approach is to use an iterator (if possible) or view (if iterator won't work). This doesn't exactly avoid two traversals, but it does avoid creation of a full-sized intermediate collection. You then map first and filter afterwards and then map again if needed:
xs.iterator.map(x => x*x).filter(_ > N).map(_.toString)
The advantage of this approach is that it's really easy to read and, since there are no intermediate collections, it's reasonably efficient.
If you are asking because this is a performance bottleneck, then the answer is usually to write a tail-recursive function or use the old-style while loop method. For instance, in your case
def sumSqBigN(xs: Array[Int], N: Int): Array[String] = {
val ysb = Array.newBuilder[String]
def inner(start: Int): Array[String] = {
if (start >= xs.length) ysb.result
else {
val sq = xs(start) * xs(start)
if (sq > N) ysb += sq.toString
inner(start + 1)
}
}
inner(0)
}
You can also pass a parameter forward in inner instead of using an external builder (especially useful for sums).
I have yet to confirm that this is truly a single pass, but:
val sqNumsLargerThanN = nums flatMap { x =>
val square = x * x
if (square > N) Some(x) else None
}
You can use collect which applies a partial function to every value of the collection that it's defined at. Your example could be rewritten as follows:
val sqNumsLargerThanN = nums collect {
case (x: Int) if (x * x) > N => (x * x).toString
}
A very simple approach that only does the multiplication operation once. It's also lazy, so it will be executing code only when needed.
nums.view.map(x=>x*x).withFilter(x => x> N).map(_.toString)
Take a look here for differences between filter and withFilter.
Consider this for comprehension,
for (x <- 0 until 10; v = x*x if v > N) yield v.toString
which unfolds to a flatMap over the range and a (lazy) withFilter onto the once only calculated square, and yields a collection with filtered results. To note one iteration and one calculation of square is required (in addition to creating the range).
You can use flatMap.
val sqNumsLargerThanN = nums flatMap { x =>
val square = x * x
if (square > N) Some(square.toString) else None
}
Or with Scalaz,
import scalaz.Scalaz._
val sqNumsLargerThanN = nums flatMap { x =>
val square = x * x
(square > N).option(square.toString)
}
The solves the asked question of how to do this with one iteration. This can be useful when streaming data, like with an Iterator.
However...if you are instead wanting the absolute fastest implementation, this is not it. In fact, I suspect you would use a mutable ArrayList and a while loop. But only after profiling would you know for sure. In any case, that's for another question.
Using a for comprehension would work:
val sqNumsLargerThanN = for {x <- nums if x*x > N } yield (x*x).toString
Also, I'm not sure but I think the scala compiler is smart about a filter before a map and will only do 1 pass if possible.
I am also beginner did it as follows
for(y<-(num.map(x=>x*x)) if y>5 ) { println(y)}

Refactoring a small Scala function

I have this function to compute the distance between two n-dimensional points using Pythagoras' theorem.
def computeDistance(neighbour: Point) = math.sqrt(coordinates.zip(neighbour.coordinates).map {
case (c1: Int, c2: Int) => math.pow(c1 - c2, 2)
}.sum)
The Point class (simplified) looks like:
class Point(val coordinates: List[Int])
I'm struggling to refactor the method so it's a little easier to read, can anybody help please?
Here's another way that makes the following three assumptions:
The length of the list is the number of dimensions for the point
Each List is correctly ordered, i.e. List(x, y) or List(x, y, z). We do not know how to handle List(x, z, y)
All lists are of equal length
def computeDistance(other: Point): Double = sqrt(
coordinates.zip(other.coordinates)
.flatMap(i => List(pow(i._2 - i._1, 2)))
.fold(0.0)(_ + _)
)
The obvious disadvantage here is that we don't have any safety around list length. The quick fix for this is to simply have the function return an Option[Double] like so:
def computeDistance(other: Point): Option[Double] = {
if(other.coordinates.length != coordinates.length) {
return None
}
return Some(sqrt(coordinates.zip(other.coordinates)
.flatMap(i => List(pow(i._2 - i._1, 2)))
.fold(0.0)(_ + _)
))
I'd be curious if there is a type safe way to ensure equal list length.
EDIT
It was politely pointed out to me that flatMap(x => List(foo(x))) is equivalent to map(foo) , which I forgot to refactor when I was originally playing w/ this. Slightly cleaner version w/ Map instead of flatMap :
def computeDistance(other: Point): Double = sqrt(
coordinates.zip(other.coordinates)
.map(i => pow(i._2 - i._1, 2))
.fold(0.0)(_ + _)
)
Most of your problem is that you're trying to do math with really long variable names. It's almost always painful. There's a reason why mathematicians use single letters. And assign temporary variables.
Try this:
class Point(val coordinates: List[Int]) { def c = coordinates }
import math._
def d(p: Point) = {
val delta = for ((a,b) <- (c zip p.c)) yield pow(a-b, dims)
sqrt(delta.sum)
}
Consider type aliases and case classes, like this,
type Coord = List[Int]
case class Point(val c: Coord) {
def distTo(p: Point) = {
val z = (c zip p.c).par
val pw = z.aggregate(0.0) ( (a,v) => a + math.pow( v._1-v._2, 2 ), _ + _ )
math.sqrt(pw)
}
}
so that for any two points, for instance,
val p = Point( (1 to 5).toList )
val q = Point( (2 to 6).toList )
we have that
p distTo q
res: Double = 2.23606797749979
Note method distTo uses aggregate on a parallelised collection of tuples, and combines the partial results by the last argument (summation). For high dimensional points this may prove more efficient than the sequential counterpart.
For simplicity of use, consider also implicit classes, as suggested in a comment above,
implicit class RichPoint(val c: Coord) extends AnyVal {
def distTo(d: Coord) = Point(c) distTo Point(d)
}
Hence
List(1,2,3,4,5) distTo List(2,3,4,5,6)
res: Double = 2.23606797749979

Scala: Implementing a mathematical recursion with convergence

Many numerical problems are of the form:
initialize: x_0 = ...
iterate: x_i+1 = function(x_i) until convergence, e.g.,
|| x_i+1 - x_i || < epsilon
I'm wondering whether there is a nice way to write such an algorithm using idiomatic Scala. The nature of the problem calls for an Iterator or Stream. However, my current take on this looks really ugly:
val xFinal = Iterator.iterate(xInit) { x_i =>
// update x_i+1
}.toList // necessary to pattern match within takeWhile
.sliding(2) // necessary since takeWhile needs pair-wise comparison
.takeWhile{ case x_i :: x_iPlus1 :: Nil => /* convergence condition */ }
.toList // since the outer container is still an Iterator
.last // to get the last element of the iteration
.last // to get x_iPlus1
This is not only ugly, the pattern matching in takeWhile also causes a warning. Obviously I do not have to pattern-match here, but I would love to keep a strong resemblance to the mathematical original.
Any ideas to make this look more beautiful?
The following minimalist (silly) example may illustrate none the less a useful framework to adapt,
def function (i:Int): Int = i+1
def iter (x0: Int): Int = {
val x1 = function(x0)
if (x1 - x0 == 1) x1 else iter(x1)
}
Here is my solution for the example of finding the square root using Newton's method, which reduces in this case to the Babylonian method:
import math.abs
val tol=0.00001
val desiredSqRoot=256
val xFinal = Iterator.iterate(1.0) { x => 0.5*(x+desiredSqRoot/x) }
def converged(l: Seq[Double]): Boolean = l match{
case x_old :: x_new :: Nil => if( abs(x_old-x_new)/x_old < tol ) true else false
case _ => true
}
xFinal.sliding(2).dropWhile( x=> !converged(x) ).next.last
which results as:
scala> xFinal.sliding(2).dropWhile( x=> !converged(x) ).next.last
res23: Double = 16.00000000000039
In this example we know the value it should converge to, yet I've written the convergence criterion without this knowledge, because in general we don't know this.

Matching with custom combinations/operators

I know that you can do matching on lists in a way like
val list = List(1,2,3)
list match {
case head::tail => head
case _ => //whatever
}
so I started to wonder how this works. If I understand correctly, :: is just an operator, so what's to stop me from doing something like
4 match {
case x + 2 => x //I would expect x=2 here
}
If there is a way to create this kind of functionality, how is it done; if not, then why?
Pattern matching takes the input and decomposes it with an unapply function. So in your case, unapply(4) would have to return the two numbers that sum to 4. However, there are many pairs that sum to 4, so the function wouldn't know what to do.
What you need is for the 2 to be accessible to the unapply function somehow. A special case class that stores the 2 would work for this:
case class Sum(addto: Int) {
def unapply(i: Int) = Some(i - addto)
}
val Sum2 = Sum(2)
val Sum2(x) = 5 // x = 3
(It would be nice to be able to do something like val Sum(2)(y) = 5 for compactness, but Scala doesn't allow parameterized extractors; see here.)
[EDIT: This is a little silly, but you could actually do the following too:
val `2 +` = Sum(2)
val `2 +`(y) = 5 // y = 3
]
EDIT: The reason the head::tail thing works is that there is exactly one way to split the head from the tail of a list.
There's nothing inherently special about :: versus +: you could use + if you had a predetermined idea of how you wanted it to break a number. For example, if you wanted + to mean "split in half", then you could do something like:
object + {
def unapply(i: Int) = Some(i-i/2, i/2)
}
and use it like:
scala> val a + b = 4
a: Int = 2
b: Int = 2
scala> val c + d = 5
c: Int = 3
d: Int = 2
EDIT: Finally, this explains that, when pattern matching, A op B means the same thing as op(A,B), which makes the syntax look nice.
Matching with case head :: tail uses an infix operation pattern of the form p1 op p2 which gets translated to op(p1, p2) before doing the actual matching. (See API for ::)
The problem with + is the following:
While it is easy to add an
object + {
def unapply(value: Int): Option[(Int, Int)] = // ...
}
object which would do the matching, you may only supply one result per value. E.g.
object + {
def unapply(value: Int): Option[(Int, Int)] = value match {
case 0 => Some(0, 0)
case 4 => Some(3, 1)
case _ => None
}
Now this works:
0 match { case x + 0 => x } // returns 0
also this
4 match { case x + 1 => x } // returns 3
But this won’t and you cannot change it:
4 match { case x + 2 => x } // does not match
No problem for ::, though, because it is always defined what is head and what is tail of a list.
There are two ::s (pronounced "cons") in Scala. One is the operator on Lists and the other is a class, which represents a non empty list characterized by a head and a tail. So head :: tail is a constructor pattern, which has nothing to do with the operator.