3
\$\begingroup\$

I have a simple task:

Given a sequence of real numbers, replace all of its members larger than Z by Z and count the number of replacements.

I solved this task using Scala, but my code looks like imperative-style code. I want to make my code more functional. How can I rewrite my program so it becomes functional-style code?

def main(args : Array[String]) {
 println("Enter Z number: ")
 val z = readDouble();
 println("Enter the length of sequence: ")
 val lenght = readInt();
 var seq: List[Double] = List();
 // Filling sequence
 for (i <- 1 to lenght) {
 println("Enter sequence item No " + i)
 val item = readDouble();
 seq = item :: seq;
 }
 // number of replacements
 var substituteCount = 0;
 //replacing all numbers larger Z by Z
 seq = seq.map(x => {if (x > z){substituteCount+= 1; z} else x})
 println("Replacement count: " + substituteCount)
 println("New sequence: " + seq.reverse.mkString(" "))
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 20, 2013 at 12:11
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Let's split this up a bit; firstly, let's put the sequence filling code in its own function:

def populateSequence(length: Int): IndexedSeq[Double] = {
 for {
 i <- 1 to length
 _ = println("Enter sequence item ? " + i)
 item = readDouble()
 } yield item
}

This utilizes the a combination of for and yield - in this case, this returns an IndexedSeq[Double], but don't worry, you can treat this like a List (or simply convert it to one with a .toList if you really want to.

Our code structure then looks like this:

def main(args: Array[String]) {
 println("Enter Z number: ")
 val z = readDouble();
 println("Enter the length of sequence: ")
 val length = readInt();
 val seq = populateSequence(length) 

Ok, where to from here? Well, in this case, instead of modifying substituteCount as we go, I'd rather just calculate it up front:

val substituteCount = seq count (_ > z)

To get our modified List (or IndexedSequence), we can use another for expression. Again, one thing to remember is that both for and if are expressions in Scala, so we can do this:

val modified = for {
 v <- seq
 item = if (v > z) z else v
} yield item

We can then print everything as usual:

println("Replacement count: " + substituteCount)
println("New sequence: " + modified.mkString(" "))
answered May 20, 2013 at 13:21
\$\endgroup\$
2
  • \$\begingroup\$ Thank you, very nice, especially this statement: val substituteCount = seq count (_ > z) :) But does val modified =... is better than using map method as in my code? I thought that the only one place in my code written in true functional style is usage of map method :) \$\endgroup\$ Commented May 20, 2013 at 14:05
  • 1
    \$\begingroup\$ map and for-expressions are actually exactly the same - under the covers, for gets converted into a map. But yeah, whichever way you prefer really - using map there is totally fine too. \$\endgroup\$ Commented May 20, 2013 at 14:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.