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

Knoldus Inc.
Knoldus - Technical Insights
5 min readJun 28, 2016

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,

[code language=”scala”]
scala> val name = null
name: Null = null

scala> name == null
res0: Boolean = true
[/code]

But in a better way it can be defined as,

[code language=”scala”]
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
[/code]

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,

[code language=”scala”]
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)
[/code]

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

[code language=”scala”]
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)
[/code]

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

[code language=”scala”]
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)
[/code]

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

[code language=”scala”]
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((), (), (), ())
[/code]

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

[code language=”scala”]
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))
[/code]

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,

[code language=”scala”]
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)
[/code]

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

[code language=”scala”]
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)
[/code]

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,

[code language=”scala”]
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]
[/code]

Now to transform we use the java converter as below,

[code language=”scala”]
scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._

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

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,

[code language=”scala”]
scala> scalaBuffer.toList
res7: List[Int] = List(100)
[/code]

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,

[code language=”scala”]
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
[/code]

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,

[code language=”scala”]
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
[/code]

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

--

--

Knoldus Inc.
Knoldus - Technical Insights

Group of smart Engineers with a Product mindset who partner with your business to drive competitive advantage | www.knoldus.com