Thursday, June 22, 2023

Why functional programming? Code Examples in Kotlin

Why functional programming? 

Functional programming has been around for almost as long as other programming paradigms, such as procedural and object-oriented programming, if not longer. But in the past 10 years, it has gained major momentum. The reason for that is because something else stalled: CPU speeds. We cannot speed up our CPUs as much as we did in the past, so we must parallelize our programs. And it turns out that the functional programming paradigm is exceptional at running parallel tasks. The evolution of multicore processors is a very interesting topic by itself, but we'll be able to cover it only briefly. Workstations had multiple processors since the 1980s at least, to support running tasks from different users in parallel. Since workstations were huge anyway, they didn't need to worry about cramming everything into one chip. But with multiprocessors coming to the consumer market around 2005, it was necessary to have one physical unit that could do work in parallel. That's the reason we have multiple cores on one chip in our PC or laptop.

But that's not the only reason some swear by functional programming. Here are a few more: 

Functional programming favors pure functions, and pure functions are usually easier to reason about and to test 

Code written in a functional way is often more declarative than imperative, dealing with the what and not the how

We have extensively studied functional programming, and anyone working in Android app development and as a Kotlin developer for back-end frameworks like Ktor knows the significant advantages that functional programming offers compared to procedural programming languages.

Immutability 

One of the key concepts of functional programming is immutability. It means that from the moment the function receives input to the moment the function returns output, the object doesn't change. How could it change, you wonder? Let's see a simple example: fun <T> printAndClear(list: MutableList<T>) {

    for (e in list) {

        println(e)

        list.remove(e)

    }

}

printAndClear(mutableListOf("a", "b", "c")) The output would be first "a", then we'll receive ConcurrentModificationException. Wouldn't it be great if we could protect ourselves from such runtime exceptions in the first place?

Tuples 

In functional programming, a tuple is a piece of data that cannot be changed after it is created. One of the most basic tuples in Kotlin is Pair: val pair = "a" to 1 Pair contains two properties, first and second, and is immutable: pair.first = "b" // Doesn't work

pair.second = 2  // Still doesn't We can destructure a Pair into two separate values: val (key, value) = pair

println("$key => $value") When iterating over a map, we receive another tuple, Map.Entry: for (p in mapOf(1 to "Sunday", 2 to "Monday")) {

   println("${p.key} ${p.value}")

}

In general, data classes are usually a good implementation for tuples. But, as we'll see in the Value Mutation section, not every data class is a proper tuple.

Value mutation 

In our earlier blog game we design as Maronic, we would like to count the average score over one thousand games. For that, we have the following 

data class: data class AverageScore(var totalScore: Int = 0,

                        var gamesPlayed: Int = 0) {

    val average: Int

        get() = if (gamesPlayed <= 0)

                    0

                else

                    totalScore / gamesPlayed

We were smart: we protected ourselves from any invalid output by checking for divisions by zero. But what will happen when we write the following code?

val counter = AverageScore()

 thread(isDaemon = true) {

    while(true) counter.gamesPlayed = 0

}

 for (i in 1..1_000) {

    counter.totalScore += Random().nextInt(100)

    counter.gamesPlayed++

println(counter.average)

Soon enough, you'll receive ArithmeticException anyway. Our counter somehow becomes zero. If you want your data classes to be immutable, be sure to specify all their properties as val (values), and not var (variables).

Immutable collections 

I think that our junior developer learned their lesson. Instead, they produced this code, which is not very efficient, but which gets rid of those variables: 

data class ScoreCollector(val scores: MutableList<Int> = mutableListOf())

 val counter = ScoreCollector()

 for (i in 1..1_000) {

    counter.scores += Random().nextInt(100)

 println(counter.scores.sumBy { it } / counter.scores.size)

But the maleficent thread strikes again:

thread(isDaemon= true, name="Maleficent") {

    while(true) counter.scores.clear()

We again receive ArithmeticException.It's not enough that your data class contains only values. If its value is a collection, it must be immutable in order for the data class to be considered immutable. The same rule is applied to classes contained within other data classes: 

data class ImmutableScoreCollector(val scores: List<Int>) 

Now the maleficent thread cannot even call clear() on this collection. But how should we add scores to it? One option is to pass the entire list in the constructor: 

val counter = ImmutableScoreCollector(List(1_000) {

    Random().nextInt(100)

})

Functions as values 

We already covered some of the functional capabilities of Kotlin to our earlier blog in Design Patterns. The Strategy and Command design patterns are but a few that heavily rely on the ability to accept functions as arguments, return functions, store them as values, or put them inside collections. In this section, we'll cover some other aspects of functional programming in Kotlin, such as function purity and currying.

Higher-order functions 

As we discussed previously, in Kotlin, it's possible for a function to return another function: 

fun generateMultiply(): (Int, Int) -> Int {

    return { x: Int, y: Int -> x * y}

Functions can also be assigned to a variable or value to be invoked later on: 

val multiplyFunction = generateMultiply()

...

println(multiplyFunction(3, 4)) 

The function assigned to a variable is usually called a literal function. It's also possible to specify a function as a parameter: 


fun mathInvoker(x: Int, y: Int, mathFunction: (Int, Int) -> Int) {

    println(mathFunction(x, y))

}

 mathInvoker(5, 6, multiplyFunction) If a function is the last parameter, it can also be supplied ad hoc, outside of the brackets: mathInvoker(7, 8) { x, y ->

   x * y

In general, a function without a name is called an anonymous function. If a function without a name uses short syntax, it's called a lambda: val squareAnonymous = fun(x: Int) = x * x

val squareLambda = {x: Int -> x * x}

Pure functions 

A pure function is a function without any side effects. Take the following function, for example: 

fun sayHello() {

    println("Hello")

How do you test to see whether "Hello" is indeed printed? The task is not as simple as it seems, as we'll need some means to capture the standard output, the same console where we usually see stuff printed. Compare it to the following function: fun hello() = "Hello" The following function doesn't have any side effects. That makes it a lot easier to test: 

fun testHello(): Boolean {

    return "Hello" == hello()

Does the hello() function look a bit meaningless to your eyes? That's actually one of the properties of pure functions.

Their invocation could be replaced by their result (if we knew all their results, that is). This is often called referential transparency. Not every function written in Kotlin is pure: 

fun <T> removeFirst(list: MutableList<T>): T {

    return list.removeAt(0)

If we call the function twice on the same list, it will return different results:

val list = mutableListOf(1, 2, 3)

println(removeFirst(list)) // Prints 1

println(removeFirst(list)) // Prints 2 Try this one: fun <T> withoutFirst(list: List<T>): T {

    return ArrayList(list).removeAt(0)

Now our function is totally predictable, no matter how many times we invoke it: val list = mutableListOf(1, 2, 3)

 println(withoutFirst(list)) // It's 1

println(withoutFirst(list)) // Still 1

As you can see, we used an immutable interface this time, List<T>, which helps us by preventing even the possibility of mutating our input. Together with immutable values from the previous section, pure functions provide a very strong tool that allows easier testing by providing predictable results and parallelization of our algorithms.

Currying 

Currying is a way to translate a function that takes a number of arguments into a chain of functions that each take a single argument. This may sound confusing, so let's look at a simple example: 

fun subtract(x: Int, y: Int): Int {

    return x - y

}

println(subtract(50, 8)) 

This is a function that returns two arguments. The result is quite obvious. But maybe we would like to invoke this function with the following syntax instead: subtract(50)(8) We've already seen how we can return a function from another function: 

fun subtract(x: Int): (Int) -> Int {

    return fun(y: Int): Int {

        return x - y

    }

Here it is in the shorter form: fun subtract(x: Int) = fun(y: Int): Int {

    return x + y

And here it is in an even shorter form: fun subtract(x: Int) = {y: Int -> x - y} Although not very useful by itself, it's still an interesting concept to grasp. And if you're a JavaScript developer looking for a new job, make sure you understand it really well, since it's being asked about in nearly every interview.

Memorization 

If our function always returns the same output for the same input, we could easily map between previous input and output, and use it as a cache. That technique is called memoization: 

class Summarizer {

    private val resultsCache = mutableMapOf<List<Int>, Double>()

 fun summarize(numbers: List<Int>): Double {

        return resultsCache.computeIfAbsent(numbers, ::sum)

    }

 private fun sum(numbers: List<Int>): Double {

        return numbers.sumByDouble { it.toDouble() }

    }

We use a method reference operator, ::, to tell computeIfAbsent to use the sum() method in the event that input wasn't cached yet. Note that sum() is a pure function, while summarize() is not. The latter will behave differently for the same input. But that's exactly what we want in this case: val l1 = listOf(1, 2, 3)

val l2 = listOf(1, 2, 3)

val l3 = listOf(1, 2, 3, 4)

val summarizer = Summarizer()

println(summarizer.summarize(l1)) // Computes, new input

println(summarizer.summarize(l1)) // Object is the same, no compute

println(summarizer.summarize(l2)) // Value is the same, no compute

println(summarizer.summarize(l3))

Computes The combination of immutable objects, pure functions, and plain old classes provides us with a powerful tool for performance optimizations. Just remember, nothing is free. We only trade one resource, CPU time, for another resource, memory. And it's up to you to decide which resource is more expensive for you in each case.

Expressions, 

expressions not statements A statement is a block of code that doesn't return anything. An expression, on the other hand, returns a new value. Since statements produce no results, the only way for them to be useful is to mutate state. And functional programming tries to avoid mutating the state as much as possible. Theoretically, the more we rely on expressions, the more our functions will be pure, with all the benefits of functional purity. We've used the if expression many times already, so one of its benefits should be clear: it's less verbose and, for that reason, less error-prone than the if statement. Pattern matching The concept of pattern matching is like switch/case on steroids for someone who comes from Java. We've already seen how when expression can be used, in Chapter 1, Getting Started with Kotlin, so let's briefly discuss why this concept is important for the functional paradigm. As you may know, switch in Java accepts only some primitive types, strings, or enums. Consider the following code in Java: 

class Cat implements Animal {

    public String purr() {

        return "Purr-purr";

    }

}

 class Dog implements Animal {

    public String bark() {

        return "Bark-bark";

    } }

 interface Animal {} 

 If we were to decide which of the functions to call, we would need something like this: 

 public String getSound(Animal animal) {

    String sound = null;

    if (animal instanceof Cat) {

        sound = ((Cat)animal).purr();

    }

    else if (animal instanceof Dog) {

        sound = ((Dog)animal).bark();

    }

 if (sound == null) {

        throw new RuntimeException();

    }

    return sound;

This method could be shortened by introducing multiple returns, but in real projects, multiple returns are usually bad practice. Since we don't have a switch statement for classes, we need to use an if statement instead. Compare that with the following Kotlin code:

fun getSound(animal: Animal) = when(animal) {

    is Cat -> animal.purr()

    is Dog -> animal.bark()

    else -> throw RuntimeException()

Since when is an expression, we avoided the intermediate variable altogether. But what's more, using pattern matching, we can also avoid most of the code that concerns type checks and casts. Recursion Recursion is a function invoking itself with new arguments: 

fun sumRec(i: Int, numbers: List<Int>): Long {

    return if (i == numbers.size) {

        0

    } else {

        numbers[i] + sumRec(i + 1, numbers)

    }

}

 We usually avoid recursion, due to Stack Overflow error that we may receive if our call stack is too deep. You can call this function with a list that contains a million numbers to experience it: 

val numbers = List(1_000_000) {it}

println(sumRec(0,  numbers)) // Crashed pretty soon, around 7K  

One of the great benefits of tail recursion is that it avoids the dreaded stack overflow exception. Let's rewrite our recursive function using a new keyword, tailrec, to avoid that problem: 

tailrec fun sumRec(i: Int, sum: Long, numbers: List<Int>): Long {

    return if (i == numbers.size) {

        return sum

    } else {

        sumRec(i+1, numbers[i] + sum, numbers)

    }

Now the compiler will optimize our call and avoid exception completely. Summary You should now have a better understanding of functional programming and its benefits. We've discussed the concepts of immutability and pure functions. A combination of the two often results in more testable code, which is easier to maintain. Currying and memoization are two useful patterns that originate from functional programming. Kotlin has a tailrec keyword that allows the compiler to optimize tail recursion. We also looked at higher-order functions, expressions versus statements, and pattern matching. In the next chapter, we'll put this knowledge to practical use, and discover how reactive programming builds upon functional programming in order to create scalable and resilient systems.

Streaming Your Data  

For Java developers, they first appeared in Java 8 with the introduction of Stream API. But they were around for much longer in functional languages. First, since we expect that many of our readers are familiar with Java 8, let's cover what Stream API is in Java briefly. Streams from Java8 are not to be confused with some of the I/O classes with similar names, such as InputStream or OutputStream. While the latter represent data, the former are sequences of elements of the same type. If those are sequences, and they all have the same type, how are they different from Lists? Well, streams can be infinite, unlike collections. There is also a set of actions defined for Java streams. Not only are those actions the same for any kind of stream,

they also have familiar names for those that come from totally different languages. There's the map() function in JavaScript, which does the same as the map() method in Java. The idea of making extensive use of small, reusable, and composable functions comes directly from functional programming, which we discussed in the previous chapter. They allow us to write code in a manner that tells what we want to do, instead of how we want to do it. But in Java, to use those functions, we have to either receive a stream or create a stream from a collection. In Java, in order to get to all this functional goodness for collections, we can do the following: 

Arrays.asList("a", "b", "c") // Initialize list

    .stream() // Convert to stream

    .map(...) // Do something functional here   

    .toList() // Convert back to list In Kotlin, you can do the same: listOf("a", "b", "c").stream().map{...}.toList() 

But all those methods and more are available directly on collections: listOf("a", "b", "c").map(...)

That's all; there is no need to convert from the stream and back unless you plan to operate on infinite data in the first place. Of course, it's not as simple as that, but we cover the differences and pitfalls near the end of this chapter, in the Streams are lazy, collections are not section. Let's start by understanding what those weird functions actually do. In this chapter, we won't be able to cover all the functions available on collections, but we'll cover the most widely used ones. The examples will be somewhat boring, mostly lists of numbers, letters, and people. That's to let you focus on how each function actually works.

The it notation 

We glanced at the notion of it briefly in previous chapters, but for this chapter, we need to understand it a bit more (pun intended). Kotlin is all about brevity. First, if our lambda doesn't have an argument, we don't need to specify anything: 

val noParameters = { 1 } // () -> Int 

implicitly But what if we have a function that takes another function as an argument (and doesn't do anything with it for simplicity)? See the following code: 

fun oneParameter(block: (Int)->Long){ } 

We can specify both the argument name and type explicitly, and wrap them in brackets, like any other function invocation: 

val oneParameterVeryVeryExplicit = oneParameter( {x: Int -> x.toLong() }) 

But since the lambda is the last parameter (and the only one, in this case), we can omit the brackets: 

val oneParameterVeryExplicit = oneParameter {x: Int -> x.toLong() } 

And since the compiler can infer the type of parameter, we can omit it too:

 val oneParameterExplicit = oneParameter {x -> x.toLong() } 

And since x is the only parameter, we can use the implicit name for it, which is it: 

val oneParameterImplicit = oneParameter { it.toLong() } 

We'll use the shortest notation in most of the following examples.

Filter family 

Another common task is filtering a collection. You know the drill. You iterate over it and put only values that fit your criteria in a new collection. For example, if given a range of numbers between 1-10, we would like to return only odd ones. Of course, we've already learned this lesson from the previous example, and wouldn't simply create a function called filterOdd(), as later we would be required to also implement filterEven(), filterPrime(), and so on. We'll receive a lambda as the second argument right away: fun filter(numbers: List<Int>, check: (Int)->Boolean): MutableList<Int> {

 val result = mutableListOf<Int>()

 for (n in numbers) {

        if (check(n)) {

            result.add(n)

        }

    }

 return result

Invoking it will print only odd numbers. How odd: println(filter((1..10).toList()) {

    it % 2 != 0

})

 // [1, 3, 5, 7, 9] And, of course, we have a built-in function that does exactly that already:

 println((1..10).toList().filter {

    it % 2 != 0

}) 

Find family Say you have an unordered list of objects: 

data class Person(val firstName: String, 

                  val lastName: String,

                  val age: Int)

val people = listOf(Person("Jane", "Doe", 19),

            Person("John", "Doe", 24),

            Person("John", "Smith", 23)) And would like to find a first object that matches some criteria. Using extension functions, you could write something like this: 

fun <T> List<T>.find(check: (T) -> Boolean): T? {

    for (p in this) {

        if (check(p)) {

            return p

        }

    }

    return null

And then, when you have a list of objects, you can simply call find() on it: 

println(people.find {

    it.firstName == "John"

}) // Person(firstName=John, lastName=Doe) 

Luckily, you don't have to implement anything. This method is already implemented for you in Kotlin. There's also an accompanying findLast() method, which does the same, but which starts with the last element of the collection: 

println(people.findLast {

    it.firstName == "John"

}) // Person(firstName=John, lastName=Smith) 

Drop family OK

this is cool if you have to iterate over all elements in your collection anyway. But with the for loops in Java, you could do something like this: // Skips first two elements

for (int i = 2; i < list.size(); i++) {

   // Do something here

} How are you going to achieve that with your funky functions, huh? Well, for that there's drop(): val numbers = (1..5).toList()

println(numbers.drop(2)) // [3, 4, 5] Do note that this doesn't modify the original collection in any way: println(numbers) // [1, 2, 3, 4, 5] If you would like to stop your loop earlier, there's dropLast() for that: println(numbers.dropLast(2)) // [1, 2, 3] Another interesting function is dropWhile(), in which it receives a predicate instead of a number. It skips until the predicate returns true for the first time: val readings = listOf(-7, -2, -1, -1, 0, 1, 3, 4)

 println(readings.dropWhile {

    it <= 0

}) // [1, 3, 4] And there's the accompanying dropLastWhile(). Sort family Don't worry, we won't have to implement our own sort algorithm. This is not CS 101. Having the list of people from the preceding find() example, we would like to sort them by age: val people = listOf(Person("Jane", "Doe", 19),

        Person("John", "Doe", 24),

        Person("John", "Smith", 23)) It is easily achieved with sortedBy(): println(people.sortedBy { it.age }) 

The preceding code prints the following output: [Person(firstName=Jane, lastName=Doe, age=19), Person(firstName=John, lastName=Smith, age=23), Person(firstName=John, lastName=Doe, age=24)] There's also sortedByDescending(), which will reverse the order of the results: println(people.sortedByDescending { it.lastName }) The preceding code prints the following output: [Person(firstName=John, lastName=Smith, age=23), Person(firstName=John, lastName=Doe, age=24), Person(firstName=Jane, lastName=Doe, age=19)] And if you want to compare by more than one parameter, use the combination of sortedWith and compareBy: println(people.sortedWith(compareBy({it.lastName}, {it.age}))) ForEach This is the first terminator we'll see. Terminator functions return something other than a new collection, so you can't chain the result of this call to other calls. In the case of forEach(), it returns Unit. So it's like the plain, old for loop: 

val numbers = (0..5)

 numbers.map { it * it}          // Can continue

       .filter { it < 20 }      // Can continue

       .sortedDescending()      // Still can

       .forEach { println(it) } // Cannot continue Do note that forEach() has some minor performance impacts compared to the traditional for loop. There's also forEachIndexed(), which provides an index in the collection alongside the actual value: numbers.map { it * it }

        .forEachIndexed { index, value ->

    print("$index:$value, ")

}

 The output for the preceding code will be as follows: 0:1, 1:4, 2:9, 3:16, 4:25,  Since Kotlin 1.1, there's also the onEach() function, which is a bit more useful, since it returns the collection again:

 numbers.map { it * it}         

       .filter { it < 20 }     

       .sortedDescending()     

       .onEach { println(it) } // Can continue now

       .filter { it > 5 }

 Join family 

In the previous example, we used the side effect of printing to the console, which is not favorable in terms of functional programming. What's more, we also have this ugly comma at the end of our output as follows: 0:1, 1:4, 2:9, 3:16, 4:25, There must be a better way. How many times have you had to actually write code to simply concatenate some list of values into a string? Well, Kotlin has a function for that:     val numbers = (1..5)

 println(numbers.joinToString { "$it"}) 

The preceding code will give the following output: 1, 2, 3, 4, 5

 Simply beautiful, isn't it? And if you want to separate it with other characters, or don't want spaces, there's a way to configure it: println(numbers.joinToString(separator = "#") { "$it"}) The output of the preceding code will be as follows: 1#2#3#4#5 Fold/Reduce Much like forEach(), both fold() and reduce() are terminating functions. But instead of terminating with Unit, which is not useful, they terminate with a single value of the same type. The most common example of reduce is, of course, for adding up stuff. With the list of people from the previous example, we can do the following:

 println(people.reduce {p1, p2 ->

        Person("Combined", "Age", p1.age + p2.age)

    }) 

The output of the preceding code will be as follows: 

Person(firstName=Combined, lastName=Age, age=64)

 Well, combining a lot of people into one doesn't make much sense, unless you're a fan of some horror movies. But with reduce, we can also compute who's the oldest or the youngest in the list:

 println(people.reduce {p1, p2 ->

    if (p1.age > p2.age) { p1 } else { p2 }

}) 

The second function we're about to discuss, fold(), is much like reduce, but it takes another argument, which is the initial value. It's useful when you've already computed something, and now want to use this intermediate result: 

println(people.drop(1) // Skipping first one

       .fold(people.first()) // Using first one as initial value

             {p1, p2 ->

    Person("Combined", "Age", p1.age + p2.age)

})

Code examples:

1.CollectionMutableExample.kt :

package functional.immutability

import java.util.*
import kotlin.concurrent.thread


fun main(args: Array<String>) {
val counter = ScoreCollector()

thread(isDaemon = true, name = "Maleficent") {
while (true) counter.scores.clear()
}

for (i in 1..1_000) {
counter.scores += Random().nextInt(100)

println(counter.scores.sumBy { it } / counter.scores.size)
}

}


data class ScoreCollector(val scores: MutableList<Int> = mutableListOf())

Output :
23 54 63 66 68 70 67 68 70 70 64 60 62 59 60 61 60 58 56 55 55 57 55 56 55 57 57 55 54 54 Exception in thread "main" java.lang.ArithmeticException: / by zero
at FileKt.main (File.kt:17)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (:-2)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (:-1)

2.CollectionImmutableExample.kt :

package functional.immutability

import java.util.*
import kotlin.concurrent.thread


fun main(args: Array<String>) {

val counter = ImmutableScoreCollector(List(1_000) {
Random().nextInt(100)
})

thread(isDaemon = true, name = "Maleficent") {
//while(true) counter.scores.clear()
}
}


data class ImmutableScoreCollector(val scores: List<Int>)


Will continue in next blog....

Sunday, June 4, 2023

Why functional programming? and its Deep Concept for Programming

 Why functional programming? 

Deep Concept of Functional programming

Functional programming has been around for almost as long as other programming paradigms, such as procedural and object-oriented programming, if not longer. But in the past 10 years, it has gained major momentum. The reason for that is because something else stalled: CPU speeds. We cannot speed up our CPUs as much as we did in the past, so we must parallelize our programs. And it turns out that the functional programming paradigm is exceptional at running parallel tasks. The evolution of multicore processors is a very interesting topic by itself, but we'll be able to cover it only briefly. Workstations had multiple processors since the 1980s at least, to support running tasks from different users in parallel. Since workstations were huge anyway, they didn't need to worry about cramming everything into one chip. But with multiprocessors coming to the consumer market around 2005, it was necessary to have one physical unit that could do work in parallel. That's the reason we have multiple cores on one chip in our PC or laptop.

But that's not the only reason some swear by functional programming. Here are a few more: 

Functional programming favors pure functions, and pure functions are usually easier to reason about and to test 

Code written in a functional way is often more declarative than imperative, dealing with the what and not the how

We have extensively studied functional programming, and anyone working in Android app development and as a Kotlin developer for back-end frameworks like Ktor knows the significant advantages that functional programming offers compared to procedural programming languages.

Immutability 

One of the key concepts of functional programming is immutability. It means that from the moment the function receives input to the moment the function returns output, the object doesn't change. How could it change, you wonder? Let's see a simple example: fun <T> printAndClear(list: MutableList<T>) {

    for (e in list) {

        println(e)

        list.remove(e)

    }

}

printAndClear(mutableListOf("a", "b", "c")) The output would be first "a", then we'll receive ConcurrentModificationException. Wouldn't it be great if we could protect ourselves from such runtime exceptions in the first place?

Tuples 

In functional programming, a tuple is a piece of data that cannot be changed after it is created. One of the most basic tuples in Kotlin is Pair: val pair = "a" to 1 Pair contains two properties, first and second, and is immutable: pair.first = "b" // Doesn't work

pair.second = 2  // Still doesn't We can destructure a Pair into two separate values: val (key, value) = pair

println("$key => $value") When iterating over a map, we receive another tuple, Map.Entry: for (p in mapOf(1 to "Sunday", 2 to "Monday")) {

   println("${p.key} ${p.value}")

}

In general, data classes are usually a good implementation for tuples. But, as we'll see in the Value Mutation section, not every data class is a proper tuple.

Value mutation 

In our earlier blog game we design as Maronic, we would like to count the average score over one thousand games. For that, we have the following 

data class: data class AverageScore(var totalScore: Int = 0,

                        var gamesPlayed: Int = 0) {

    val average: Int

        get() = if (gamesPlayed <= 0)

                    0

                else

                    totalScore / gamesPlayed

We were smart: we protected ourselves from any invalid output by checking for divisions by zero. But what will happen when we write the following code?

val counter = AverageScore()

 thread(isDaemon = true) {

    while(true) counter.gamesPlayed = 0

}

 for (i in 1..1_000) {

    counter.totalScore += Random().nextInt(100)

    counter.gamesPlayed++

println(counter.average)

Soon enough, you'll receive ArithmeticException anyway. Our counter somehow becomes zero. If you want your data classes to be immutable, be sure to specify all their properties as val (values), and not var (variables).

Immutable collections 

I think that our junior developer learned their lesson. Instead, they produced this code, which is not very efficient, but which gets rid of those variables: 

data class ScoreCollector(val scores: MutableList<Int> = mutableListOf())

 val counter = ScoreCollector()

 for (i in 1..1_000) {

    counter.scores += Random().nextInt(100)

 println(counter.scores.sumBy { it } / counter.scores.size)

But the maleficent thread strikes again:

thread(isDaemon= true, name="Maleficent") {

    while(true) counter.scores.clear()

We again receive ArithmeticException.It's not enough that your data class contains only values. If its value is a collection, it must be immutable in order for the data class to be considered immutable. The same rule is applied to classes contained within other data classes: 

data class ImmutableScoreCollector(val scores: List<Int>) 

Now the maleficent thread cannot even call clear() on this collection. But how should we add scores to it? One option is to pass the entire list in the constructor: 

val counter = ImmutableScoreCollector(List(1_000) {

    Random().nextInt(100)

})

I am not going to tell you about Kotlin as it is very clearly written on Kotlin Developer site .However i have tried to give gist on Functional programming .

Functions as values 
We already covered some of the functional capabilities of Kotlin to our earlier blog in Design Patterns. The Strategy and Command design patterns are but a few that heavily rely on the ability to accept functions as arguments, return functions, store them as values, or put them inside collections. In this section, we'll cover some other aspects of functional programming in Kotlin, such as function purity and currying.

Higher-order functions 
As we discussed previously, in Kotlin, it's possible for a function to return another function: 
fun generateMultiply(): (Int, Int) -> Int {
    return { x: Int, y: Int -> x * y}
Functions can also be assigned to a variable or value to be invoked later on: 
val multiplyFunction = generateMultiply()
...
println(multiplyFunction(3, 4)) 
The function assigned to a variable is usually called a literal function. It's also possible to specify a function as a parameter: 

fun mathInvoker(x: Int, y: Int, mathFunction: (Int, Int) -> Int) {
    println(mathFunction(x, y))
}
 mathInvoker(5, 6, multiplyFunction) If a function is the last parameter, it can also be supplied ad hoc, outside of the brackets: mathInvoker(7, 8) { x, y ->
   x * y
In general, a function without a name is called an anonymous function. If a function without a name uses short syntax, it's called a lambda: val squareAnonymous = fun(x: Int) = x * x
val squareLambda = {x: Int -> x * x}

Pure functions 
A pure function is a function without any side effects. Take the following function, for example: 
fun sayHello() {
    println("Hello")
How do you test to see whether "Hello" is indeed printed? The task is not as simple as it seems, as we'll need some means to capture the standard output, the same console where we usually see stuff printed. Compare it to the following function: fun hello() = "Hello" The following function doesn't have any side effects. That makes it a lot easier to test: 
fun testHello(): Boolean {
    return "Hello" == hello()
Does the hello() function look a bit meaningless to your eyes? That's actually one of the properties of pure functions.
Their invocation could be replaced by their result (if we knew all their results, that is). This is often called referential transparency. Not every function written in Kotlin is pure: 
fun <T> removeFirst(list: MutableList<T>): T {
    return list.removeAt(0)
If we call the function twice on the same list, it will return different results:
val list = mutableListOf(1, 2, 3)
println(removeFirst(list)) // Prints 1
println(removeFirst(list)) // Prints 2 Try this one: fun <T> withoutFirst(list: List<T>): T {
    return ArrayList(list).removeAt(0)
Now our function is totally predictable, no matter how many times we invoke it: val list = mutableListOf(1, 2, 3)
 println(withoutFirst(list)) // It's 1
println(withoutFirst(list)) // Still 1

As you can see, we used an immutable interface this time, List<T>, which helps us by preventing even the possibility of mutating our input. Together with immutable values from the previous section, pure functions provide a very strong tool that allows easier testing by providing predictable results and parallelization of our algorithms.

Currying 
Currying is a way to translate a function that takes a number of arguments into a chain of functions that each take a single argument. This may sound confusing, so let's look at a simple example: 
fun subtract(x: Int, y: Int): Int {
    return x - y
}
println(subtract(50, 8)) 
This is a function that returns two arguments. The result is quite obvious. But maybe we would like to invoke this function with the following syntax instead: subtract(50)(8) We've already seen how we can return a function from another function: 
fun subtract(x: Int): (Int) -> Int {
    return fun(y: Int): Int {
        return x - y
    }
Here it is in the shorter form: fun subtract(x: Int) = fun(y: Int): Int {
    return x + y
And here it is in an even shorter form: fun subtract(x: Int) = {y: Int -> x - y} Although not very useful by itself, it's still an interesting concept to grasp. And if you're a JavaScript developer looking for a new job, make sure you understand it really well, since it's being asked about in nearly every interview.

Memorization 
If our function always returns the same output for the same input, we could easily map between previous input and output, and use it as a cache. That technique is called memoization: 
class Summarizer {
    private val resultsCache = mutableMapOf<List<Int>, Double>()
 fun summarize(numbers: List<Int>): Double {
        return resultsCache.computeIfAbsent(numbers, ::sum)
    }
 private fun sum(numbers: List<Int>): Double {
        return numbers.sumByDouble { it.toDouble() }
    }
We use a method reference operator, ::, to tell computeIfAbsent to use the sum() method in the event that input wasn't cached yet. Note that sum() is a pure function, while summarize() is not. The latter will behave differently for the same input. But that's exactly what we want in this case: val l1 = listOf(1, 2, 3)
val l2 = listOf(1, 2, 3)
val l3 = listOf(1, 2, 3, 4)
val summarizer = Summarizer()
println(summarizer.summarize(l1)) // Computes, new input
println(summarizer.summarize(l1)) // Object is the same, no compute
println(summarizer.summarize(l2)) // Value is the same, no compute
println(summarizer.summarize(l3))

Computes The combination of immutable objects, pure functions, and plain old classes provides us with a powerful tool for performance optimizations. Just remember, nothing is free. We only trade one resource, CPU time, for another resource, memory. And it's up to you to decide which resource is more expensive for you in each case.

Expressions, 
expressions not statements A statement is a block of code that doesn't return anything. An expression, on the other hand, returns a new value. Since statements produce no results, the only way for them to be useful is to mutate state. And functional programming tries to avoid mutating the state as much as possible. Theoretically, the more we rely on expressions, the more our functions will be pure, with all the benefits of functional purity. We've used the if expression many times already, so one of its benefits should be clear: it's less verbose and, for that reason, less error-prone than the if statement. Pattern matching The concept of pattern matching is like switch/case on steroids for someone who comes from Java. We've already seen how when expression can be used, in Chapter 1, Getting Started with Kotlin, so let's briefly discuss why this concept is important for the functional paradigm. As you may know, switch in Java accepts only some primitive types, strings, or enums. Consider the following code in Java:
 
class Cat implements Animal {
    public String purr() {
        return "Purr-purr";
    }
}
 class Dog implements Animal {
    public String bark() {
        return "Bark-bark";
    } }
 interface Animal {} 
 
 If we were to decide which of the functions to call, we would need something like this: 
 
 public String getSound(Animal animal) {
    String sound = null;
    if (animal instanceof Cat) {
        sound = ((Cat)animal).purr();
    }
    else if (animal instanceof Dog) {
        sound = ((Dog)animal).bark();
    }
 if (sound == null) {
        throw new RuntimeException();
    }
    return sound;

This method could be shortened by introducing multiple returns, but in real projects, multiple returns are usually bad practice. Since we don't have a switch statement for classes, we need to use an if statement instead. Compare that with the following Kotlin code:
 
fun getSound(animal: Animal) = when(animal) {
    is Cat -> animal.purr()
    is Dog -> animal.bark()
    else -> throw RuntimeException()

Since when is an expression, we avoided the intermediate variable altogether. But what's more, using pattern matching, we can also avoid most of the code that concerns type checks and casts. 

Recursion

Recursion is a function invoking itself with new arguments: 

fun sumRec(i: Int, numbers: List<Int>): Long {
    return if (i == numbers.size) {
        0
    } else {
        numbers[i] + sumRec(i + 1, numbers)
    }
}
 We usually avoid recursion, due to Stack Overflow error that we may receive if our call stack is too deep. You can call this function with a list that contains a million numbers to experience it: 
val numbers = List(1_000_000) {it}
println(sumRec(0,  numbers)) // Crashed pretty soon, around 7K  

One of the great benefits of tail recursion is that it avoids the dreaded stack overflow exception. Let's rewrite our recursive function using a new keyword, tailrec, to avoid that problem: 

tailrec fun sumRec(i: Int, sum: Long, numbers: List<Int>): Long {
    return if (i == numbers.size) {
        return sum
    } else {
        sumRec(i+1, numbers[i] + sum, numbers)
    }

Now the compiler will optimize our call and avoid exception completely. Summary You should now have a better understanding of functional programming and its benefits. We've discussed the concepts of immutability and pure functions. A combination of the two often results in more testable code, which is easier to maintain. Currying and memoization are two useful patterns that originate from functional programming. Kotlin has a tailrec keyword that allows the compiler to optimize tail recursion. We also looked at higher-order functions, expressions versus statements, and pattern matching. In the next chapter, we'll put this knowledge to practical use, and discover how reactive programming builds upon functional programming in order to create scalable and resilient systems.


Observer Design Pattern with Kotlin

 Observer Design Patterns

Observer this design pattern will provide us with a bridge and dedicated to functional programming. So, what is Observer pattern about? You have one publisher, which may also be called a subject, that may have many subscribers, which may also be called observers. Each time something interesting happens with the publisher, it should update all of its subscribers. This may look a lot like the Mediator design pattern, but there's a twist. Subscribers should be able to register or unregister themselves at runtime. In the classical implementation, all subscribers/observers need to implement a certain interface in order for the publisher to be able to update them. But since Kotlin has higher-order functions, we can omit this part. The publisher will still have to provide means for observers to be able to subscribe and unsubscribe.

Animal Choir 

So, animals have decided to have a choir of their own. The cat was elected as the conductor of the choir (it didn't like to sing anyway). The problem is that animals escaped from the Java world, and don't have a common interface. Instead, each has a different method to make a sound: 

class Bat {

    fun screech() {

        println("Eeeeeee")

    }

}

 class Turkey {

    fun gobble() {

        println("Gob-gob")

    }

}

 class Dog {

    fun bark() {

        println("Woof")

    }

 fun howl() {

        println("Auuuu")

}

Luckily, the cat was elected not only because it was vocally challenged, but also because it was smart enough to follow this chapter until now. So it knows that in the Kotlin world, it can accept functions: 

class Cat {

    ...

    fun joinChoir(whatToCall: ()->Unit) {

        ...

    }

 fun leaveChoir(whatNotToCall: ()->Unit) {

        ...

    }

    ...

Previously, we've seen how to pass a new function as an argument, as well as passing a literal function. But how do we pass a reference to a member function? That's what member reference operator is for—::: 

val catTheConductor = Cat()

val bat = Bat()

val dog = Dog()

val turkey = Turkey()

catTheConductor.joinChoir(bat::screech)

catTheConductor.joinChoir(dog::howl)

catTheConductor.joinChoir(dog::bark)

catTheConductor.joinChoir(turkey::gobble) 

Now the cat needs to save all those subscribers somehow. Luckily, we can put them on a map. What would be the key? It could be the function itself: 

class Cat {

 private val participants = mutableMapOf<()->Unit, ()->Unit>()

 fun joinChoir(whatToCall: ()->Unit) {

        participants.put(whatToCall, whatToCall)

    }

    ...

If all those ()->Unit instances are making you dizzy, be sure to use typealias to give them more semantic meaning, such as subscriber. The bat decides to leave the choir. After all, no one is able to hear its beautiful singing anyway: 

class Cat {

    ...

    fun leaveChoir(whatNotToCall: ()->Unit) {

        participants.remove(whatNotToCall)

}

    ...

All Bat needs to do is to pass its subscriber function again: catTheConductor.leaveChoir(bat::screech) That's the reason we used the map in the first place. Now Cat can call all its choir members and tell them to sing. Well, produce sounds: typealias Times = Int

 class Cat {

    ...

    fun conduct(n: Times) {

        for (p in participants.values) {

            for (i in 1..n) {

                p()

            }

        }

    }

The rehearsal went well. But Cat feels very tired after doing all those loops. It would rather delegate the job to choir members. That's not a problem at all:

class Cat {

    private val participants = mutableMapOf<(Int)->Unit, (Int)->Unit>()

 fun joinChoir(whatToCall: (Int)->Unit) {

        ...

    }

 fun leaveChoir(whatNotToCall: (Int)->Unit) {

        ...

    }

 fun conduct(n: Times) {

        for (p in participants.values) {

            p(n)

        }

    }

Our subscribers all look like turkeys here: class Turkey {

    fun gobble(repeat: Times) {

        for (i in 1..repeat) {

            println("Gob-gob")

        }

    }

Actually, it is a bit of a problem. What if the Cat was to tell each animal what sound to make: high or low? We'll have to change all subscribers again, and the Cat too.

While designing your publisher, pass single data classes with many properties, instead of sets of data classes or other types. That way, you'll have to refactor your subscribers less, in case new properties are added: 

enum class SoundPitch {HIGH, LOW}

data class Message(val repeat: Times, val pitch: SoundPitch)

 class Bat {

    fun screech(message: Message) {

        for (i in 1..message.repeat) {

            println("${message.pitch} Eeeeeee")

        }

    }

Make sure that your messages are immutable. Otherwise, you may experience strange behavior! What if you have sets of different messages you're sending from the same publisher? Use smart casts: 

interface Message {

    val repeat: Times

    val pitch: SoundPitch 

}

 data class LowMessage(override val repeat: Times) : Message {

 override val pitch = SoundPitch.LOW

}

 data class HighMessage(override val repeat: Times) : Message {

    override val pitch = SoundPitch.HIGH

}

class Bat {

    fun screech(message: Message) {

        when (message) {

            is HighMessage -> {

                for (i in 1..message.repeat) {

                    println("${message.pitch} Eeeeeee")

                }

            }

            else -> println("Can't :(")

        }

    }

}

Code Example :

package designpatterns.observer


fun main(args: Array<String>) {


val catTheConductor = Cat()

val bat = Bat()
val dog = Dog()
val turkey = Turkey()

catTheConductor.joinChoir(bat::screech)
catTheConductor.joinChoir(dog::howl)
catTheConductor.joinChoir(dog::bark)
catTheConductor.joinChoir(turkey::gobble)

catTheConductor.conduct(LowMessage(2))
println()

catTheConductor.leaveChoir(bat::screech)
catTheConductor.conduct(HighMessage(1))
}

typealias Times = Int

enum class SoundPitch { HIGH, LOW }
interface Message {
val repeat: Times
val pitch: SoundPitch
}

data class LowMessage(override val repeat: Times) : Message {
override val pitch = SoundPitch.LOW
}

data class HighMessage(override val repeat: Times) : Message {
override val pitch = SoundPitch.HIGH
}

class Cat {
private val participants = mutableMapOf<(Message) -> Unit,
(Message) -> Unit>()

fun joinChoir(whatToCall: (Message) -> Unit) {
participants.put(whatToCall, whatToCall)
}

fun leaveChoir(whatNotToCall: (Message) -> Unit) {
participants.remove(whatNotToCall)
}

fun conduct(message: Message) {
for (p in participants.values) {
p(message)
}
}
}

class Bat {
fun screech(message: Message) {
when (message) {
is HighMessage -> {
for (i in 1..message.repeat) {
println("${message.pitch} Eeeeeee")
}
}

else -> println("Can't :(")
}
}
}

class Turkey {
fun gobble(message: Message) {
for (i in 1..message.repeat) {
println("${message.pitch} Gob-gob")
}
}
}

class Dog {
fun bark(message: Message) {
for (i in 1..message.repeat) {
println("${message.pitch} Woof")
}
}

fun howl(message: Message) {
for (i in 1..message.repeat) {
println("${message.pitch} Auuuu")
}
}
}

Ouput :

Can't :( LOW Auuuu LOW Auuuu LOW Woof LOW Woof LOW Gob-gob LOW Gob-gob HIGH Auuuu HIGH Woof HIGH Gob-gob

Summary 

That was a long chapter. But we've also learned a lot. We finished covering all classical design patterns, including eleven behavioral ones. In Kotlin, functions can be passed to other functions, returned from functions, and assigned to variables. That's what the "functions as first-class citizens" concept is all about. If your class is all about behavior, it often makes sense to replace it with a function. Iterator is yet another operator in the language. Sealed classes help in making when statements exhaustive. The run extension function allows for controlling what will be returned from it. A lambda with a receiver allows more clear syntax in your DSLs. Another keyword, lateinit, tells the compiler to relax a bit in its null safety checks. Use with care! And finally, we covered how to reference an existing method with ::. In the next blog, we'll move on from an object-oriented programming paradigm with its well-known design patterns to another paradigm—functional programming.


Template Method Design Pattern with Kotlin and Comparative Analysis with Java

 Template method Design Patterns

Template method Some lazy people make art out of their laziness. Take me for example. Here's my daily schedule: 8:00–9:00: Arrive at the office 9:00–10:00: Drink coffee 10:00–12:00: Attend some meetings or review code 12:00–13:00: Go out for lunch 13:00–16:00: Attend some meetings or review code 16:00: Sneak out home As you can see, some of the parts of the schedule never change, and some do. At first, I thought I could decorate my changing schedule with that setup and teardown logic, which happens before and after. But then there's lunch, which is holy for architects and happens in between. Java is pretty clear on what you should do. First, you create an abstract class. All methods that you want to implement by yourself you mark as private: 

abstract class DayRoutine {

    private fun arriveToWork() {


println("Hi boss! I appear in the office sometimes!")

    }

 private fun drinkCoffee() {

        println("Coffee is delicious today")

    }

 ...

 private fun goToLunch() {

        println("Hamburger and chips, please!")

    }

 ...

 private fun goHome() {

        // Very important no one notices me

        println()

    }

 ...

For all methods that are changing from day to day, you define an abstract: 

abstract class DayRoutine {

    ...

    abstract fun doBeforeLunch()

    ...

    abstract fun doAfterLunch()

    ...

}


If you allow the changing of a method, but want to provide a default implementation, you leave it public: 

abstract class DayRoutine {

    ...

    open fun bossHook() {

        // Hope he doesn't hook me there

    }

    ...

And finally, you have a method that executes your algorithm. It's final by default: 

abstract class DayRoutine {

    ...

    fun runSchedule() {

        arriveToWork()

        drinkCoffee()

        doAfterLunch()

        goToLunch()

        doAfterLunch()

        goHome()

    }

If we now want to have a schedule for Monday, we simply implement the missing parts: 

class MondaySchedule : DayRoutine() {

    override fun doBeforeLunch() {

        println("Some pointless meeting")


println("Code review. What this does?")

    }

 override fun doAfterLunch() {

        println("Meeting with Ralf")

        println("Telling jokes to other architects")

    }

 override fun bossHook() {

        println("Hey, can I have you for a sec in my office?")

    }

What does Kotlin add on top of that? What it usually does—conciseness. As we've seen previously, this can be achieved through functions. We have three moving parts—two mandatory activities (the software architect must do something before and after lunch) and one optional (the boss may stop him before he sneaks off home or not): 

fun runSchedule(beforeLunch: ()->Unit,

                afterLunch: ()->Unit,

                bossHook: (()->Unit)? = fun() { println() }) {

    ...

We'll have a function that accepts up to three other functions as its arguments. The first two are mandatory, and the third may not be supplied at all, or assigned with

null to explicitly state that we don't want that function to happen: fun runSchedule(...) {

    ...

    arriveToWork()

    drinkCoffee()

    beforeLunch()

    goToLunch()

    afterLunch()

    bossHook?.let { it() }

    goHome()

Inside this function, we'll have our algorithm. Invocations of beforeLunch() and afterLunch() should be clear; after all, those are the functions that are passed to us as arguments. The third one, bossHook, may be null, so we execute it only if it's not: ?.let { it() }. But what about the other functions, those we want to always implement by ourselves? Kotlin has a notion of local functions. Those are functions that reside in other functions: 

fun runSchedule(...) {

    fun arriveToWork(){

        println("How are you all?")

    }

val drinkCoffee = { println("Did someone left the milk out?") }

 fun goToLunch() = println("I would like something italian")

 val goHome = fun () {

        println("Finally some rest")

    }

 arriveToWork()

    drinkCoffee()

    ...

    goToLunch()

    ... goHome()

Those are all valid ways to declare a local function. No matter how you define them, they're invoked in the same way. We're left with the same result, as you can see. Define the algorithm structure, but let others decide what to do at some points: that's what the Template Method is all about.

Code Example :

With Kotlin Example :

package designpatterns.templateMethod


fun main(args: Array<String>) {
runSchedule(afterLunch = fun() {
println("Discuss my lunch with boss' secretary")
println("Read something not related to work")
}, beforeLunch = {
println("Look for my next trip destination")
println("Read StackOverflow")
}, bossHook = { println("Boss: Can we talk privately?") })
}


fun runSchedule(
beforeLunch: () -> Unit,
afterLunch: () -> Unit,
bossHook: (() -> Unit)? = fun() { println() }
) {
fun arriveToWork() {
println("How are you all?")
}

val drinkCoffee = { println("Did someone left the milk out?") }

fun goToLunch() = println("I would like something italian")

val goHome = fun() {
println("Finally some rest")
}

arriveToWork()
drinkCoffee()
beforeLunch()
goToLunch()
afterLunch()
bossHook?.let { it() }
goHome()
}

Output :
How are you all? Did someone left the milk out? Look for my next trip destination Read StackOverflow I would like something italian Discuss my lunch with boss' secretary Read something not related to work Boss: Can we talk privately? Finally some rest

With Java Example :

package chapter4.templateMethod

abstract class DayRoutine {
private fun arriveToWork() {
println("Hi boss! I appear in the office sometimes!")
}

private fun drinkCoffee() {
println("Coffee is delicious today")
}

abstract fun doBeforeLunch()

private fun goToLunch() {
println("Hamburger and chips, please!")
}

abstract fun doAfterLunch()

open fun bossHook() {
// Hope he doesn't hook me there
}

private fun goHome() {
// Very important no one notices me
println()
}

fun runSchedule() {
arriveToWork()
drinkCoffee()
doAfterLunch()
goToLunch()
doAfterLunch()
bossHook()
goHome()
}
}

class MondaySchedule : DayRoutine() {
override fun doBeforeLunch() {
println("Some pointless meeting")
println("Code review. What this does?")
}

override fun doAfterLunch() {
println("Meeting with Ralf")
println("Telling jokes to other architects")
}

override fun bossHook() {
println("Hey, can I have you for a sec in my office?")
}
}

I hope you are able to understand the difference with code examples.


Visitor Design Patterns with Kotlin and comparative analysis with Java

 Visitor Design Patterns

This design pattern is usually a close friend of the Composite design pattern Structural Patterns. It can either extract data from a complex tree-like structure or add behavior to each node of the tree, much like the Decorator design pattern. So, my plan, being a lazy software architect, worked out quite well. Both my mail-sending system from Builder and my request-answering system from Chain of Responsibility worked quite well. But some developers still begin to suspect that I'm a bit of a fraud. To confuse them, I plan to produce weekly emails with links to all the latest buzzword articles. Of course, I don't plan to read them myself, just collect them from some popular technology sites.

Writing a crawler 

Let's look at the following structure, which is very similar to what we had when discussing the Iterator design pattern: 

Page(Container(Image(),Link(),Image()),Table(),Link(),

     Container(Table(),

               Link()),

     Container(Image(),

               Container(Image(),

                         Link()))) 

The Page is a container for other HtmlElements, but not HtmlElement by itself. Container holds other containers, tables, links, and images. Image holds its link in the src attribute. Link has the href attribute instead. We start by creating a function that will receive the root of our object tree, a Page in this case, and return a list of all available links: 

fun collectLinks(page: Page): List<String> {

    // No need for intermediate variable there

return LinksCrawler().run {

        page.accept(this)

        this.links

    }

Using run allows us to control what we return from the block body. In this case, we would return the links we've gathered. In Java, the suggested way to implement the Visitor design pattern is to add a method for each class that would accept our new functionality. We'll do the same, but not for all classes. Instead, we'll define this method only for container elements: 

private fun Container.accept(feature: LinksCrawler) {

    feature.visit(this)

}

 // Same as above but shorter

private fun Page.accept(feature: LinksCrawler) = feature.visit(this) Our feature will need to hold a collection internally, and expose it only for read purposes. In Java, we would specify only the getter and no setter for that member. In Kotlin, we can specify the value without a backing field: 

class LinksCrawler {

    private var _links = mutableListOf<String>()

val links

        get()= _links.toList()

    ...

We wish for our data structure to be immutable. That's the reason we're calling toList() on it. The functions that iterate over branches could be further simplified if we use the Iterator design pattern. For containers, we simply pass their elements further: class LinksCrawler {

    ...

    fun visit(page: Page) {

        visit(page.elements)

    }

 fun visit(container: Container) = visit(container.elements)

    ...

Specifying the parent class as sealed helps the compiler further: 


sealed class HtmlElement

class Container(...) : HtmlElement(){

    ...

}

 class Image(...) : HtmlElement() {

    ...

}

 class Link(...) : HtmlElement() {

    ...

}

 class Table : HtmlElement() The most interesting logic is in the leaves: class LinksCrawler {

    ...

    private fun visit(elements: List<HtmlElement>) {

        for (e in elements) {

            when (e) {

                is Container -> e.accept(this)

                is Link -> _links.add(e.href)

                is Image -> _links.add(e.src)

                else -> {}

            }

        }

    }

Note that in some cases, we don't want to do anything. That's specified by an empty block in our else: else -> {}.

That's the first time we've seen smart casts in Kotlin. Notice that after we checked that the element is a Link, we gained type-safe access to its href attribute. That's because the compiler is doing the casts for us. The same holds true for the Image element as well. Although we achieved our goals, the usability of this pattern can be argued. As you can see, it's one of the more verbose elements, and introduces tight coupling between classes receiving additional behavior and Visitor itself.

Code Example :

package designpattern.visitor

fun main(args: Array<String>) {

val page = Page(
Container(
Image(),
Link(),
Image()
),
Table(),
Link(),
Container(
Table(),
Link()
),
Container(
Image(),
Container(
Image(),
Link()
)
)
)

println(collectLinks(page))
}

fun collectLinks(page: Page): List<String> {
// No need for intermediate variable there
return LinksCrawler().run {
page.accept(this)
this.links
}
}


class LinksCrawler {
private var _links = mutableListOf<String>()

val links
get() = _links.toList()

fun visit(page: Page) {
visit(page.elements)
}

fun visit(container: Container) = visit(container.elements)

private fun visit(elements: List<HtmlElement>) {
for (e in elements) {
when (e) {
is Container -> e.accept(this)
is Link -> _links.add(e.href)
is Image -> _links.add(e.src)
else -> {}
}
}
}
}

private fun Container.accept(feature: LinksCrawler) {
feature.visit(this)
}

// Same as above but shorter
private fun Page.accept(feature: LinksCrawler) = feature.visit(this)


class Page(val elements: MutableList<HtmlElement> = mutableListOf()) {
constructor(vararg elements: HtmlElement) : this(mutableListOf()) {
for (s in elements) {
this.elements.add(s)
}
}
}


sealed class HtmlElement

class Container(val elements: MutableList<HtmlElement> = mutableListOf()) :
                                                       HtmlElement() {

constructor(vararg units: HtmlElement) : this(mutableListOf()) {
for (u in units) {
this.elements.add(u)
}
}
}

class Image : HtmlElement() {
val src: String
get() = "http://some.image"
}

class Link : HtmlElement() {
val href: String
get() = "http://some.link"
}

class Table : HtmlElement()

Output :

[http://some.image, http://some.link,

http://some.image, http://some.link,

http://some.link, http://some.image,

http://some.image,

http://some.link]





Friday, June 2, 2023

Memento Design Pattern with Kotlin

 Memento Design Patterns

Since Abhi became a manager, it's been very hard to catch him if I have a question. And when I do ask him something, he just throws something and runs to the next meeting. Yesterday, I asked him what the next weapon we would introduce in our Maronic game should be. He told me it should be a Coconut Cannon, clear as day. But today, when I presented him with this feature, he chirped at me angrily! He said he told me to implement a Pineapple Launcher instead. I'm lucky he's just a canary still... But it would be great if I could just record him, and when we have another meeting that goes awry because he's not paying full attention, I would just replay everything he said.

Remembrance 

Summing up my problems first—Abhi's thoughts are his and his only: 

class Manager {

    private var lastThought = "Should get some coffee"

    private var repeatThat = 3

    private var thenHesitate = "Or maybe tea?"

    private var secretThought = "No, coffee it is"

    ...

Moreover, they're quite complex and scattered. I have no access to them, but only to their byproduct: 

class Manager {

    ...

    fun whatAreYouThinking() {

        for (i in 1..repeatThat) {

            println(lastThought)

        }

        println(thenHesitate)

    }

    ...

}

Even recording what he says is quite hard (because he doesn't return anything).

And even if I did record him, Abhi can claim it's what he said, not what he meant: Why did you bring me tea? I wanted coffee! The solution may seem quite obvious. Let's use an inner class, thought, that will capture this last thought:

class Manager {

    ...

    class Thought {

        fun captureThought(): CapturedThought {

            return CapturedThought(lastThought, 

                                   repeatThat,                              

                                   thenHesitate, 

                                   secretThought)

        }

    }

 data class CapturedThought(val thought: String, 

                               val repeat: Int, 

                               val hesitate: String,

                               val secret: String)

The only problem is that this code doesn't compile. It's because we're missing a new keyword, inner, to mark our class. If we omit this keyword, the class is called Nested, and is similar to the static nested class from Java. Now we can record what Abhi says at this moment:

val abhi = Manager()

 val captured = abhi.Thought().captureThought() Let's assume that abhi changes his mind at some point. We'll add another function for that: 

 class Manager {

    ...

    fun anotherThought() {

        lastThought = "Tea would be better"

        repeatThat = 2

        thenHesitate = "But coffee is also nice"

        secretThought = "Big latte would be great"

    }

}

abhi.anotherThought() 

We can always repeat the thought that we captured: 

abhi.whatAreYouThinking() This will print: 

Tea would be better

Tea would be better

But coffee is also nice Let's check what we've captured: 

println(captured)

This will print: CapturedThought(thought=Should get some coffee, repeat=3, hesitate=Or maybe tea?, secret=No, coffee it is) We can even rewind Abhi's thoughts if he would allow it:

 class Manager {

    ...

    inner class Thought {

        ...

        fun rewindThought(val previousThought: CapturedThought) {

            with(previousThought) {

                lastThought = thought

                repeatThat = repeat

                thenHesitate = hesitate

                secretThought = secret

            }

        }

    }

    ...

}

Note how here we use the with standard function to avoid repeating previousThought on each line.

Code Example :

package designpatterns.memento

fun main(args: Array<String>) {
val abhi = Manager()

val captured = abhi.Thought().captureThought()
abhi.anotherThought()
abhi.whatAreYouThinking()
println(captured)
}

class Manager {
private var lastThought = "Should get some coffee"
private var repeatThat = 3
private var thenHesitate = "Or maybe tea?"
private var secretThought = "No, coffee it is"
fun whatAreYouThinking() {
for (i in 1..repeatThat) {
println(lastThought)
}
println(thenHesitate)
}

inner class Thought {
fun captureThought(): CapturedThought {
return CapturedThought(lastThought, repeatThat, thenHesitate, secretThought)
}

fun rewindThought(previousThought: CapturedThought) {
with(previousThought) {
lastThought = thought
repeatThat = repeat
thenHesitate = hesitate
secretThought = secret
}
}
}

data class CapturedThought(
val thought: String, val repeat: Int, val hesitate: String, val secret: String
)

fun anotherThought() {
lastThought = "Tea would be better"
repeatThat = 2
thenHesitate = "But coffee is also nice"
secretThought = "Big latte would be great"
}
}

Output :

Tea would be better Tea would be better But coffee is also nice CapturedThought(thought=Should get some coffee,

repeat=3, hesitate=Or maybe tea?, secret=No, coffee it is)