5 min read

(For more resources related to this topic, see here.)

Writing an algorithm in Java follows an imperative style, that is, a sequence of statements that change a program state. Scala, focusing primarily on functional programming, adopts a more declarative approach, where everything is an expression rather than a statement. Let’s illustrate this in an example.

In Java, you would commonly find the following code snippet:

... String customerLevel = null; if(amountBought > 3000) { customerLevel = "Gold"; } else { customerLevel = "Silver"; } ...

The Scala equivalent consists of the following code snippet:

scala> val amountBought = 5000 amountBought: Int = 5000 scala> val customerLevel = if (amountBought> 3000) "Gold" else "Silver" customerLevel: String = Gold

Note that unlike the Java statements, if is now embedded as part of the resulting evaluated expression.

In general, working where everything is evaluated as an expression (and here an immutable expression) will make it much easier for reuse as well as composition.

Being able to chain the result of one expression to the next will give you a concise way of expressing fairly complicated transformations that would require much more code in Java.

Adjusting the code layout

As the intent of functional programming is to minimize state behavior, it often consists of short lambda expressions so that you can visualize a fairly complicated transformation in an elegant and concise way, in many cases even as one-liners. For this reason, general formatting in Scala recommends that you use only two-space indentations instead of the four-space indentation that is generally admitted in Java code, as shown in the following code snippet:

scala> class Customer( val firstName: String, val lastName: String, val age: Int, val address: String, val country: String, valhasAGoodRating: Boolean ) { override def toString() = s" $firstName $lastName" } defined class Customer

If you have many constructor/method parameters, having them aligned as previously illustrated makes it easier to change them without the need to reformat the whole indentation. It is also the case if you want to refactor the class with a longer name, for example, VeryImportantCustomer instead of Customer; it will make smaller and more precise differences against your version control management system (Git, subversion, and so on).

Naming conventions

Conventions for naming packages, classes, fields, and methods in the camel case generally follow the Java conventions. Note that you should avoid the underscore (_) in variable names (such as first_name or _first_name) as the underscore has a special meaning in Scala (self or this in anonymous functions).

However, constants, most likely declared as private static final myConstant in Java, are normally declared in Scala in the upper camel case, such as in the following enclosing object:

scala> object Constants { | val MyNeverChangingAge = 20 | } defined module Constants

Choosing a meaningful name for variables and methods should always be a priority in Java, and it is often recommended to use rather long variable names to precisely describe what a variable or method represents. In Scala, things are a little bit different; meaningful names are, of course, a good way to make code more readable. However, as we are at the same time aiming at making behavior transformations concise through the use of functions and lambda expressions, short variable names can be an advantage if you can capture a whole piece of functionality in a short block of code. For example, incrementing a list of integers in Scala can simply be expressed as follows:

scala> val amounts = List(3,6,7,10) map ( x => x +1 ) amounts: List[Int] = List(4, 7, 8, 11)

Although using x as a variable name is often discouraged in Java, here it does not matter that much as the variable is not reused and we can capture the transformation it does at once. There are many short or long alternatives to the previous lambda syntax that will produce the same result. So, which one to choose? Some of the alternatives are as follows:

scala> val amounts = List(3,6,7,10) map ( myCurrentAmount => myCurrentAmount +1 ) amounts: List[Int] = List(4, 7, 8, 11)

In this case, a long variable name breaks a clear and concise one-liner into two lines of code, thereby, making it difficult to understand. Meaningful names make more sense here if we start expressing logic on several lines as shown in the following code snippet:

scala> val amounts = List(3,6,7,10) map { myCurrentAmount => val result = myCurrentAmount + 1 println("Result: " + result) result } Result: 4 Result: 7 Result: 8 Result: 11 amounts: List[Int] = List(4, 7, 8, 11)

A shorter but still expressive name is sometimes a good compromise to indicate to the reader that this is an amount we are currently manipulating in our lambda expression, as follows:

scala> val amounts = List(3,6,7,10) map( amt => amt + 1 ) amounts: List[Int] = List(4, 7, 8, 11)

Finally, the shortest syntax of all that is well accepted by fluent Scala programmers for such a simple increment function is as follows:

scala> val amounts = List(3,6,7,10) map( _ + 1 ) amounts: List[Int] = List(4, 7, 8, 11)

Underscores are also encountered in Scala for expressing more complicated operations in an elegant but more awkward way, as is the following sum operation using the foldLeft method that accumulates the state from one element to the other:

scala> val sumOfAmounts = List(3,6,7,10).foldLeft(0)( _ + _ ) sumOfAmounts: Int = 26

Instead of explicitly having 0 as the initial value for the sum, we can write this summation a bit more elegantly by using the reduce method that is similar to foldLeft. However, we take the first element of the collection as the initial value (here, 3 will be the initial value), as shown in the following command:

scala> val sumOfAmounts = List(3,6,7,10) reduce ( _ + _ ) sumOfAmounts: Int = 26

As far as style is concerned, fluent Scala programmers will not have any problem reading this code. However, if the state accumulation operation is more complicated than just a simple + operation, it might be wise to write it more explicitly as shown in the following command:

scala> val sumOfAmounts = List(3,6,7,10) reduce ( (total,element) => total + element ) sumOfAmounts: Int = 26

Summary

In this article, we discussed about the style differences and the naming conventions that we must be aware of, to write easier-to-read and more maintainable code.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here