Reading Time: 5 minutes

Hi Folks,

In this series we talk about the concepts that provide a better definition to the code written in scala. We provide the methods with some definitions that lead to perform a task in a better way. Lets have a look at what we have done in the series so far,

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

Here we covered the better solution to code, so that it cannot lead the any kind of code styling or formatting errors behind. Provided the way to use scala properties and collections in a better way according to their behaviour.

Effective Programming In Scala – Part 2 : Monads as a way for abstract computations in Scala

Here we provided short hand solutions to the long and lengthy writing of code to perform some task in a predefined sequence. Provided the better use of comprehensions so that functionality depending upon Monads can be easily performed.

Now in this blog we continue to explain the concepts that can be used to tell the scala to use the desired value types and generate the monkey patches in way of Scala.

Type Annotations versus Ascription

In Scala we know that if we do not define the type of a variable, then it takes its type itself,

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

However we can control the type of a value to be a byte, int or string as well,

scala> val name: String = "John" name: String = John scala> val age: Int = 25 age: Int = 25 scala> val salary: Double = 25000.0 salary: Double = 25000.0

If we make the code to use the desired form, we type the following,

scala> val bonus = 5000.75 : Double bonus: Double = 5000.75 scala> val name = "John" : String name: String = John

As we can see that compiler provides the definition to the type as we need, but when we want to provide own definition or override the type of value, then we can use type annotations as well.

Ascription

Scala Ascription is same approach as compared with the annotations, but with a slight difference. Sometimes a new developer of Scala can be confused with both annotations and ascriptions. Ascription can be taken as a process of up-casting of a type and annotations as simple way of defining the result, we want from an expression after its execution.

In the following examples, we can show the ascription clearly.

We have bonus as of Double type and salary of object type. As you can see here, we want the salary to be of an Object type, otherwise it must not be compiled with String or unmatching type.

scala> val bonus: Double = 3000.75 bonus: Double = 3000.75 scala> val salary = bonus: Object salary: Object = 3000.75 scala> val name: String = "John" name: String = John scala> val salary = name: Double <console>:8: error: type mismatch; found : String required: Double val salary = name: Double

Now have a look at the below example, where the Ascription can be applied in another way,

val numberList = (1 to 5).toList numberList.foldLeft(Nil: List[Int]) { (table, currentNumber) => table :+ (currentNumber * 2) } numberList.headOption.fold(Left("List is empty"): Either[String, Int]) { number => Right(number * 2) }

In above code we used the (Nil: List[Int]) and (Left(“List is empty”): Either[String, Int]) are another examples of ascriptions.

Adding methods to class in implicit way

In functional programming, we often desire to add some cool functionalities to the existing classes in our project. A class plays a very important role in project development. The class is defined to hold the a huge part of the project’s functions. If we want some cool thing to our class, we should go with the following.

scala> class BetterWay(val s: String) { | def increment = s.map(c => (c + 1).toChar) | } defined class BetterWay

Here we define a class BetterWay having a methods, which returns next positioned character from ASCII standards, for every single character of the input word.

Now we define the magic below,

scala> implicit def stringToString(s: String) = new BetterWay(s) warning: there was one feature warning; re-run with -feature for details stringToString: (s: String)BetterWay

Here we defined a method stringToString which takes an input string, and passes it to the BetterWay class for further processing. Now we provide some data to test it,

scala> "hal".increment res0: String = ibm

Finally we put the word hal and got all the characters of this incremented by one and resulting into ASCII values ibm.

Lets see whats happening here…

Method stringToString is a simple methods defined in Scala. But as it is defined along the keyword implicit, then it has something more. The implicit does the magic here,

A method defined as implicit, stringToString in our case, takes a string and looks up the BetterWay class and searches for every method which accepts a string as its parameter.

Methods increment defined in class processes the string, iterates over each of its character and then gets the character next to it from ASCII values.

It does not matter whatever name you are providing for the method name for stringToString.

Monkey Patching

Now as we have the idea of implicits and how they work and perform their task, we take a similar concept under control as Monkey Patching. If a user comes from the Ruby’s background, then he always finds the implicits as another way for monkey patching. Monkey Patching in ruby is used to extend the existing class without creating a new class. Now have a look at the below example,

object NumberDefinition extends App { implicit class DefinitionHelper(val num: Int) { def isEven = { num % 2 == 0 } def isOdd = { num % 2 != 0 } } 50.isEven // true 51.isOdd // true }

Here we defined an implicit DefinitionHelper class to that accepts a value to be of Int type, which leads the class to inherit all Int members and convert any Int in scope to DefinitionHelper.

The big difference between Ruby and Scala is that Scala applies the implicit in the current scope. We can call and import the implicits anywhere without littering the global namespace resulting into less collisions and more compact DSLs.

Following points must be remembered while declaring implicits in Scala,

Implicits must be defined inside of another trait, class or any object,

We can have only one non-implicit parameter in constructor,

Scala defines the same name as of class for an object as companion object. Keeping this point in mind, We cannot have another object or member with same name as of class in scope.

So i think this blog will help you a lot in enhancing the power of scala by type system and implicits.

Happy Blogging!!!