Thursday, December 28, 2017

Back2Basics: Do you know Scala Eta-Expansion and HOF Chemistry?

I am working on Scala from last 2 years, and pretty confident about Scala concept like HOF, Currying and more. But Recently again looking into the HOF (Higher Order Functions) in Scala. I am pretty confident, HOF is "Passed a function as an argument", "Assign functions to variables" and "Return functions from function" and the conclusion is Functions are First Class Citizen.

For me, these below statements are equal:-


First is, anonymous function or lambda expression and second is a function with the name. But we can pass these two function to any function which accepts the function as an argument with this signature Int => Int.

While I am trying to execute these two statements in scala REPL, but this time I noticed, the output of these two statements are different, which insist me to investigate why this behavior?


The first line of code initializes some lambda expression but the second one defines as a function signature.

NOTE: In Scala 2.12.x Function[x] traits act as a Java 8 lambda expression rather than anonymous inner classes.  

After that, while I am looking into the Scala collection API `def map[B] (f: (A) ⇒ B)List[B]` method argument which looks like `val func = .. ` type but different from `def funcd ... ` type.

So, next question is, while I am trying to execute code using func and funcd with Listmap`  method, the code execution is successful???


But If we try to assign def funcd.. to the variable, We are getting this error.


After investigation the whole stuff, We are found the answer in one or two words called "Eta-Expansion". This term itself is a broad term. But in the layman term compiler use Eta-Expansion for convert  `def func ...` type to `lambda expression` or before Scala 2.12.x it converts into traits Function[x].

So, while we are trying to assign def func ... into the variable, we need to trigger Eta-Expansion manually which in Scala called Partially Applied Functions.


For Eta-Expansion, you can further read:
If you want to see the compiler translation, copy the whole bunch of code into scala file and compile using `$ scalac -Xprint:all Test.scala` command.


These are thousands of lines are going to print, which I have no idea, what happens under the hood, but for us, the important part is Eta-Expansion which happens below:


I am using translation as compiler steps, but not sure what we called. But according to above output, we can estimate somethings automatically happen in the case of the list as same as while we trigger Eta-Expansion manually.

Saturday, December 23, 2017

Developers Needs SDKMAN Not Super-Man


Every developer has pain for setup development environment to his/her machine with lots of the setups. Sometimes, the pain goes beyond while we need to test same application on multiple versions of sdks or virtual machines.


If you are a Mac user, you have the best option called brew installer.




But if you are Linux user, your pain is unpredictable. 






We are Java developers and Linux users and have the same pain for setting development environment with lots of configuration and different versions virtual machines.

For the sake of innocent developers, for the sake of time, we are going to introduce our superhero called SDKMAN. Which saves us from the cruel world of setup developments tools.



Technical Introduction:  


SDKMAN! is a tool for managing parallel versions of multiple Software Development Kits on most Unix based systems. It provides a convenient Command Line Interface (CLI) and API for installing, switching, removing and listing Candidates. SDKMAN is primary used for JVM based languages and framework. In future, they were plan to move SDKMAN for other environments as well. Currently SDKMAN have a huge list of sdks, which we get from here

Install SDKMAN

$ curl -s "https://get.sdkman.io" | bash

$ source "$HOME/.sdkman/bin/sdkman-init.sh"

$ sdk version

Install Java

For installing java, SDK provide simple and easy command as below:


$ sdk install java

Downloading: java 8u152-zulu

In progress...

######################################################################## 100.0%

Repackaging Java 8u152-zulu...

Done repackaging...

Installing: java 8u152-zulu
Done installing!


Setting java 8u152-zulu as default.
root@a33316a976d9:~/.sdkman# java -version
openjdk version "1.8.0_152"
OpenJDK Runtime Environment (Zulu 8.25.0.1-linux64) (build 1.8.0_152-b16)
OpenJDK 64-Bit Server VM (Zulu 8.25.0.1-linux64) (build 25.152-b16, mixed mode)

By default, sdkman download the zulu or open source JDK of java. But if we require installing some specific version of JDK or Specific Oracle JDK, what can we do???


SDKMAN gave us the way to download sdk's with specific versions as well. We can easily list out the existing SDK's which SDKMAN support and install it as per requirements.


$ sdk list

================================================================================
Available Candidates
================================================================================
q-quit                                  /-search down
j-down                                  ?-search up
k-up                                    h-help

--------------------------------------------------------------------------------
Ant (1.10.1)                                             https://ant.apache.org/

Apache Ant is a Java library and command-line tool whose mission is to drive
processes described in build files as targets and extension points dependent
upon each other. The main known usage of Ant is the build of Java applications.
Ant supplies a number of built-in tasks allowing to compile, assemble, test and
run Java applications. Ant can also be used effectively to build non Java

So on ...................

$ sdk list java

================================================================================
Available Java Versions
================================================================================
     9.0.1-zulu                                                                    
     9.0.1-oracle                                                                  
     9.0.0-zulu                                                                    
 > * 8u152-zulu                                                                    
     8u151-oracle                                                                  
     8u144-zulu                                                                    
     8u131-zulu                                                                    
     7u141-zulu                                                                    
     6u93-zulu                              
	 
$ sdk install java 8u151-oracle

Oracle requires that you agree with the Oracle Binary Code License Agreement
prior to installation. The license agreement can be found at:

  http://www.oracle.com/technetwork/java/javase/terms/license/index.html

Do you agree to the terms of this agreement? (Y/n): y


Downloading: java 8u151-oracle

In progress...

######################################################################## 100.0%

Repackaging Java 8u151-oracle...

Done repackaging...

Installing: java 8u151-oracle
Done installing!

Do you want java 8u151-oracle to be set as default? (Y/n): y

Setting java 8u151-oracle as default.

$ java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

As it shows, we can install oracle java successfully. But, at the start of this blog, as we discussed we can install multiple version of the same SDK easily and manage easily. If we go through the blog again, first we install OpenJDK after we are installing OracleJDK, single machine multiple JDKS and we also set OracleJDK as default, so how can we use OpenJDK as per our requirements??

Below are powerfull and ease commands of SDKMAN which help us to achieve this functionality.


$ sdk list java

================================================================================
Available Java Versions
================================================================================
     9.0.1-zulu                                                                    
     9.0.1-oracle                                                                  
     9.0.0-zulu                                                                    
   * 8u152-zulu                                                                    
 > * 8u151-oracle                                                                  
     8u144-zulu                                                                    
     8u131-zulu                                                                    
     7u141-zulu                                                                    
     6u93-zulu                                                                     
                                                                                   
                                                                                   
                                                                                   
                                                                                   
                                                                                   
                                                                                   

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================


$ java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

$ sdk use java 8u152-zulu

$ java -version
openjdk version "1.8.0_152"
OpenJDK Runtime Environment (Zulu 8.25.0.1-linux64) (build 1.8.0_152-b16)
OpenJDK 64-Bit Server VM (Zulu 8.25.0.1-linux64) (build 25.152-b16, mixed mode)

I am sure, now you can feel the power of SDKMAN and how easy is using this tool. This makes developers life happy and safe.


References: 

  1. http://sdkman.io/index.html
  2. Thanks to google funny images.

Sunday, July 2, 2017

Cinnamon: Way For Monitoring & Metrics Generation for Akka ActorSystem.

We are developing huge applications and deployed on multiple virtual machines and clusters. For monitoring applications, we need to enable logs into our application and analysis that logs with help of some tools like elastic stack.
But !! what if we need to check health of our application on virtual machines and clusters? For that, we are using several Metrics for system health check like Gauges, Histograms and more.

Lightbend Telemetry gives us one of the way for metrics generation and monitoring systems (application) by using Cinnamon plugins. Today's we look into Cinnamon for monitoring akka ActorSytem. Configuring cinnamon is not a rocket science, there are simple steps, which, we are going to define here.

The first step for using cinnamon is, we need to create and account on lightbend, from where we can download credentials and paste into our home directory(for linux users). All instructions are define in this link.

Note: For today's example, we are using sbt project, but we can easily integrate with maven and gradle as well.

>>> We need to add cinnamon plugin in our plugin.sbt file as below:


>>> Now, require to add some dependencies to add in our build.sbt:


>>> Add cinnamon configuration on application.conf as below:


There are lots of option for configure monitoring to actor system, for more information please click on this link.

Example: 

My example is a simple hello world actor application, but when we run that example, in console we are seeing cinnamon metrics. The example as below:


For running the application we need to execute sbt run command as below:


As in logs, we have seeing, 4 types of metrics are there. Every metrics have its own befits and analysis. These metrics gives us a report on akka actor systems like actors count, threads count, mailbox capacity and more.

For more examples, you can check github repo.

References:



Saturday, April 29, 2017

Scala Dessign Patterns: Memoization

Introduction

Memoization is mechanism of recording a function results based on its arguments in order to reduce computation in consecutive calls.

Agenda:

  • Implement Memoization using Scala.
  • Implement Memoization using Scalaz.

 

Code: By Scala


class Hasher extends Memoizer {

  val memoMd5 = memo(md5)

  private def md5(input: String) = {
    println(s"Calling md5 for $input")
    new String(Base64.getEncoder.encode(input.getBytes()))
  }
}

trait Memoizer {

  def memo[X, Y](f: X => Y): X => Y = {
    val cache = mutable.Map[X, Y]()
    (x: X) => cache.getOrElseUpdate(x, f(x))
  }
}

object MemoizationExample extends App {


  val hasher = new Hasher

  println(s"Encode for 'hello' is '${hasher.memoMd5("hello")}'")
  println(s"Encode for 'bye' is '${hasher.memoMd5("bye")}'")
  println(s"Encode for 'hello1' is '${hasher.memoMd5("hello1")}'")
  println(s"Encode for 'hello' is '${hasher.memoMd5("hello")}'")
  println(s"Encode for 'bye' is '${hasher.memoMd5("bye")}'")

}

Code: By Scalaz


class Hasher {

  val memoMd5Scalaz: String => String = Memo.mutableHashMapMemo(md5)

  private def md5(input: String) = {
    println(s"Calling md5 for $input")
    new String(Base64.getEncoder.encode(input.getBytes()))
  }
}

object MemoizationScalazExample extends App {

  val hasher = new Hasher

  println(s"Encode for 'hello' is '${hasher.memoMd5Scalaz("hello")}'")
  println(s"Encode for 'bye' is '${hasher.memoMd5Scalaz("bye")}'")
  println(s"Encode for 'hello1' is '${hasher.memoMd5Scalaz("hello1")}'")
  println(s"Encode for 'hello' is '${hasher.memoMd5Scalaz("hello")}'")
  println(s"Encode for 'bye' is '${hasher.memoMd5Scalaz("bye")}'")
}

Download Code from Github Repo

 

References:

Scala Dessign Patterns: Duck Typing

Introduction

If it looks like a duck, swims like a duck and quack like a duck then it is probably a duck.

It is not the type of object matters but the operations that the objects supports. We can use duck typing for requiring even more methods to be available for an object by just expanding the parameter signature.

Caution: Overusing duck typing can negatively affect the code quality and application performance

 

Agenda:

Duck Typing using Scala

 Code:


class SentenceParserSplit {

  def parse(sentence: String): Array[String] = sentence.split("\\s+")
}

class SentenceParserTokenize {

  def parse(sentence: String): Array[String] = {
    val tokenizer = new StringTokenizer(sentence)
    Iterator.continually({
      val hasMore = tokenizer.hasMoreTokens
      if(hasMore) {
        (hasMore, tokenizer.nextToken())
      } else {
        (hasMore, null)
      }
    }).takeWhile(_._1).map(_._2).toArray
  }
}

object WithDuckTyping {

  def printSentenceParser(sentence: String,
                          parser: {def parse(sentence: String): Array[String]}) = {
    parser.parse(sentence).foreach(println)
  }

  def main(args: Array[String]): Unit = {
    val tokenizerParser = new SentenceParserTokenize
    val splitParser = new SentenceParserSplit

    val sentence = "This is the sentence we will be splitting"

    println("Using the tokenizer parser ... ")
    printSentenceParser(sentence, tokenizerParser)

    println("Using the split parser ... ")
    printSentenceParser(sentence, splitParser)
  }
}

Download Code from Github Repo

 

References:

Scala Dessign Patterns: Lazy Evaluation

Introduction

Lazy Evaluation makes sure that an expression is evaluated only once when it is actually needed.

Agenda:

Lazy Evaluation using Scala

Code:



case class Person(name: String)
class PersonService {
  def getFromDatabase: List[Person] = {
    println("Start fetching data .... ")
    Thread.sleep(3000)
    List(Person("Knoldus"), Person("James"), Person("Taara"))
  }

  def withoutLazyEvaluation(persons: => List[Person]) = {
    println(s"Evaluate Without Lazy First Time ${persons}")
    println(s"Evaluate Without Lazy Second Time ${persons}")
  }

  def withLazyEvaluation(persons: => List[Person]) = {
    lazy val personsCopy = persons
    println(s"Evaluate With Lazy First Time ${personsCopy}")
    println(s"Evaluate With Lazy Second Time ${personsCopy}")
  }
}
object LazyEvaluation extends App {

  val service = new PersonService()
  service.withoutLazyEvaluation(service.getFromDatabase)
  service.withLazyEvaluation(service.getFromDatabase)
}

Download Code from Github Repo

 

References:

Scala Dessign Patterns: Type Class Pattern

Introduction

An important principle of good code design is to avoid repetition and it is known as do not repeat yourself (DRY).

Ad Hoc Polymorphism: 

Ad Hoc Polymorphism is utilizing a possibly different implementations based on Types. 

Agenda

  • Implement Type Class Pattern using Scala.
  • Implement Type Class Pattern using Simulacrum.

Code: By Scala


trait Number[T] {

  def plus(t1: T, t2: T): T
  def minus(t1: T, t2: T): T
  def divide(t1: T, t2: Int): T
  def multiply(t1: T, t2: T): T
  def sqrt(t1: T): T
}

object Number {
  implicit object DoubleNumber extends Number[Double] {
    override def plus(t1: Double, t2: Double): Double = t1 + t2
    override def minus(t1: Double, t2: Double): Double = t1 - t2
    override def divide(t1: Double, t2: Int): Double = t1 / t2
    override def multiply(t1: Double, t2: Double): Double = t1 * t2
    override def sqrt(t1: Double): Double = Math.sqrt(t1)
  }

  implicit object IntNumber extends Number[Int] {
    override def plus(t1: Int, t2: Int): Int = t1 + t2 + 10
    override def minus(t1: Int, t2: Int): Int = t1 - t2
    override def divide(t1: Int, t2: Int): Int = t1 / t2
    override def multiply(t1: Int, t2: Int): Int = t1 * t2
    override def sqrt(t1: Int): Int = Math.sqrt(t1).toInt
  }
}


class StatsExample {

  def mean[T: Number] (xs: Vector[T]): T = implicitly[Number[T]]
    .divide (xs.reduce(implicitly[Number[T]].plus(_, _)), xs.size)

  //assume vector is in sorted order
  def median[T: Number] (xs: Vector[T]): T = xs(xs.size / 2)
}

object StatsExample extends App {

  val intVector = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25)
  val doubleVector = Vector(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,
    20.0, 21.0, 22.0, 23.0, 24.0, 25.0)

  val example = new StatsExample
  println(s"Mean (int) ${example.mean(intVector)}")
  println(s"Median (int) ${example.median(intVector)}")

  println(s"Mean (double) ${example.mean(doubleVector)}")
  println(s"Median (double) ${example.median(doubleVector)}")
}

Code: By Simulacrum


@typeclass trait Number[T] {

  @op("+") def plus(t1: T, t2: T): T
  @op("-") def minus(t1: T, t2: T): T
  @op("/") def divide(t1: T, t2: Int): T
  @op("*") def multiply(t1: T, t2: T): T
  @op("^") def sqrt(t1: T): T
}

object Number {
  implicit object DoubleNumber extends Number[Double] {
    override def plus(t1: Double, t2: Double): Double = t1 + t2
    override def minus(t1: Double, t2: Double): Double = t1 - t2
    override def divide(t1: Double, t2: Int): Double = t1 / t2
    override def multiply(t1: Double, t2: Double): Double = t1 * t2
    override def sqrt(t1: Double): Double = Math.sqrt(t1)
  }

  implicit object IntNumber extends Number[Int] {
    override def plus(t1: Int, t2: Int): Int = t1 + t2
    override def minus(t1: Int, t2: Int): Int = t1 - t2
    override def divide(t1: Int, t2: Int): Int = t1 / t2
    override def multiply(t1: Int, t2: Int): Int = t1 * t2
    override def sqrt(t1: Int): Int = Math.sqrt(t1).toInt
  }
}


class StatsExample {

  import Number.ops._

  def mean[T: Number] (xs: Vector[T]): T = xs.reduce(_ + _) / xs.size

  //assume vector is in sorted order
  def median[T: Number] (xs: Vector[T]): T = xs(xs.size / 2)
}

object StatsExample extends App {


  val intVector = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25)
  val doubleVector = Vector(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,
    20.0, 21.0, 22.0, 23.0, 24.0, 25.0)

  val example = new StatsExample
  println(s"Mean (int) ${example.mean(intVector)}")
  println(s"Median (int) ${example.median(intVector)}")

  println(s"Mean (double) ${example.mean(doubleVector)}")
  println(s"Median (double) ${example.median(doubleVector)}")
}

Download Code from Github Repo

 

References: