Effective Programming In Scala – Part 3 : Powering Up your code implicitly in Scala


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!!!


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.

2 Responses to Effective Programming In Scala – Part 3 : Powering Up your code implicitly in Scala

  1. Keltinray says:

    When using implicit classes, would it not be better to have the classes extend AnyVal to avoid unnecessary object allocations? Of course this can’t always be done if your extensions require extra state, but for simple convenience methods like you have used here, would it not be better? Or do newer versions of Scala automatically do this?

  2. Reblogged this on Play!ng with Scala and commented:
    Discover type annotations versus ascriptions, adding methods to class in implicit way and monkey patching.

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