Effective Programming In Scala – Part 1 : Standardizing code in better way


A language is a set of standards. One has to follow them in order to avail benefits from the language. In order to maintain these standards, code in Scala has to be written in order to minimize the errors whether they are related with the concepts like redundancy of operations, use of properties of language those not supported by ScalaStyle or ScapeGoat or other checkers.

The standard of code is maintained in order to write a block of code having few lines and perform large operations effectively. In order to follow the effective standard of Scala, we can go through the following conditions and what should be their standard representations,

Matching without null

Sometimes we want to match a value whether it is a string or something that returns a null in case of default case, the code to simply match it is written as,

scala> val name = null
name: Null = null

scala> name == null
res0: Boolean = true

But in a better way it can be defined as,

scala> val name = null
name: Null = null

scala> Option(name).isDefined
res3: Boolean = false

scala> val name = "John"
name: String = John

scala> Option(name).isDefined
res4: Boolean = true

Indices of List

In few cases when we want to read the content of many collections at the same time or we say, we want to iterate more than one list at a time and get the element of another list at the same time, we prefer the following code for simplicity,

scala> val names = List("John", "Doc", "Stephen", "Doe")
names: List[String] = List(John, Doc, Stephen, Doe)

scala> val age = List(20, 30, 40, 50)
age: List[Int] = List(20, 30, 40, 50)

scala> 0 until names.length map (nameIndex => age(nameIndex))
res8: scala.collection.immutable.IndexedSeq[Int] = Vector(20, 30, 40, 50)

In a better way to iterate the indices of a list, we can rewrite the above code as,

scala> val names = List("John", "Doc", "Stephen", "Doe")
names: List[String] = List(John, Doc, Stephen, Doe)

scala> val age = List(20, 30, 40, 50)
age: List[Int] = List(20, 30, 40, 50)

scala> names.indices map (nameIndex => age(nameIndex))
res9: scala.collection.immutable.IndexedSeq[Int] = Vector(20, 30, 40, 50)

Avoid map

In Scala, the map is commonly and most frequently used to iterate a collection. But sometimes there can be the following two conditions possible,

  • We return some value,
  • We return a unit, in case of performing any file content writing operations
scala> val names = List("John", "Doc", "Stephen", "Doe")
names: List[String] = List(John, Doc, Stephen, Doe)

scala> names map (name => name.toUpperCase)
res11: List[String] = List(JOHN, DOC, STEPHEN, DOE)

In above case map returns a list of string, so it is good to use the it here.

scala> val writer = new java.io.PrintWriter("/tmp/AnyFile.txt")
writer: java.io.PrintWriter = java.io.PrintWriter@35ef439e

scala> val names = List("John", "Doc", "Stephen", "Doe")
names: List[String] = List(JOHN, Doc, Stephen, Doe)

scala> names map (name => writer.print(name))
res12: List[Unit] = List((), (), (), ())

In above case we are not returning any value, so here we should replace map with foreach as below,

scala> val writer = new java.io.PrintWriter("/tmp/AnyFile.txt")
writer: java.io.PrintWriter = java.io.PrintWriter@35ef439e

scala> val names = List("John", "Doc", "Stephen", "Doe")
names: List[String] = List(John, Doc, Stephen, Doe)

scala> names foreach (name => writer.print(name))

Avoid map over match

Sometimes if we are in situation where we have a list defining some values may be defined or undefined (Options). Now to iterate the code is written as below,

scala> val names = List(Some("John"), Some("Sam"), None, None)
names: List[Option[String]] = List(Some(John), Some(Sam), None, None)

scala> val DEFAULT = "NOT_FOUND"
DEFAULT: String = NOT_FOUND

scala> names.map { currentName =>
| currentName match {
| case Some(name) => name
| case None => DEFAULT
| }
| }
res17: List[String] = List(John, Sam, NOT_FOUND, NOT_FOUND)

Above the names are already being mapped, so we can remove the match there,

scala> val names = List(Some("John"), Some("Sam"), None, None)
names: List[Option[String]] = List(Some(John), Some(Sam), None, None)

scala> val DEFAULT = "NOT_FOUND"
DEFAULT: String = NOT_FOUND

scala> names.map {
| case Some(name) => name
| case None => DEFAULT
| }
res18: List[String] = List(John, Sam, NOT_FOUND, NOT_FOUND)

Java Converters

While programming in Scala, there are certain conditions where we face the code written in java specially while using any external api’s, whose documentation is written in java. So, java converters provide a better way of transforming these java properties into Scala.

Suppose we have an ArrayList of java utility package as below,

scala> import java.util._
import java.util._

scala> val arrayList = new ArrayList[Int]()
arrayList: java.util.ArrayList[Int] = []

scala> arrayList.add(100)
res6: Boolean = true

scala> print(arrayList)
[100]

Now to transform we use the java converter as below,

scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._

scala> val scalaBuffer = arrayList.asScala
scalaBuffer: scala.collection.mutable.Buffer[Int] = Buffer(100)

Now in the above code, we transformed the java ArrayList into mutable buffer of scala, Now we can easily change it to a list of scala,

scala> scalaBuffer.toList
res7: List[Int] = List(100)

Collections over Conditions

Sometimes we have a number of choices so that a value must match with any of them, at that time the easy approach is to match that element with those choices as below,

scala> val name = "whisky"
name: String = whisky

scala> if (((name == "vodka" || name == "teacher") || (name == "whisky")) || (name == "slice" || name == "fruity")) true else false
res0: Boolean = true

Above code wants to verify, which type of drink does the name belong to. Code is simple but not easily understandable and complex to be programmed. The code can be written as below using collection,

scala> val name = "whisky"
name: String = whisky

scala> val alchoholicDrinks = List("vodka", "teacher", "whisky")
alchoholicDrinks: List[String] = List(vodka, teacher, whisky)

scala> val softDrinks = List("slice", "fruity")
softDrinks: List[String] = List(slice, fruity)

scala> if(alchoholicDrinks.contains(name) || softDrinks.contains(name)) true else false
res1: Boolean = true

Now we defined two groups having their respective drinks. And it is easily understandable.

So there are some practices in scala, so that code can be rewritten in more effective way.

Happy Blogging !!


KNOLDUS-advt-sticker

About Harsh Sharma Khandal

Harsh is a Sr. Software Consultant at Knoldus Software LLP with 4 year of experience. He is a fan of programming standards and conventions. He has good knowledge of Scala, Java, 3D Modeling and 3D animation. His current passions include utilizing the power of Scala, Akka and Play to make reactive applications. He is a technologist and is never too far away from the keyboard. He believes in standard coding practices. His focus always remains on practical work. He has Master's in Computer Applications from Rajasthan Technical University, Kota. His hobbies include reading books and writing the code in multiple ways to find the best way it can be represented.
This entry was posted in Scala and tagged , , , , , , , , , . Bookmark the permalink.

4 Responses to Effective Programming In Scala – Part 1 : Standardizing code in better way

  1. Marco says:

    Nice article, just a quick contribution, I think the main reason to use map vs foreach is wheter you want to explicitly have side effects, map is used to transform values of a collection while foreach just execute a piece of code that returns nothing, so probably the piece of code in the foreach function will have a side effect.

  2. omdivo says:

    if(alchoholicDrinks.contains(name) || softDrinks.contains(name)) true else false should be replaced by simply alchoholicDrinks.contains(name) || softDrinks.contains(name)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s