Accumulator Pattern for beginners | Fold vs Reduce | AndroidBites

kotlin Aug 06, 2020

Worse fate you put your codebase in when you don't focus on such primitive Pattern

“oncreatedigest”
Disclaimer : All the assets used as background belongs to respective companies I don't promote them as my own, they are just used to make code relatable and attractive.


Accumulator pattern is one the most used pattern in programming, knowingly unknowingly every developer is using it daily without even realising it. If you don't know what it is, let me demonstrate using an example :

 var total = 0
 val items = listOf(1,2,3,4,5,6,7,8,9)
 for(item in items){
        total+=item
 }
 println(total) 
 //output : 45
Kotlin | Accumulator pattern

You might have got the gist, in accumulator pattern we are accumulating a computation into a variable, from above example that variable would be total.

This style of programming is also called the imperative style of programming. You might have heard this term a lot because there has been numerous debates in community regarding, which kind of programming style is better - imperative or functional?.

This article won't focus on that but I would like to add, both styles have their own benefits and we should consider mixing the concepts they bring together in order to get the most out of them.

Let's focus on the shortcoming of the above example and try to overcome :


  var total = 0 
  
  // `total` is a mutable property i.e. if someone can 
  // access it, then can change its value. We need to
  // make sure that doesn’t happen,a variable should be local to its
  // logic and shouldn’t be updated outside the scope.
  // This variable needs to be `val`, `private` or both. 
  // If we consider this to be in a function then `private` isn't
  // the option and same problem will persist.

  val items = listOf(1,2,3,4,5,6,7,8,9)
  for(item in items){
        
        total+=item 
        // we only want our variable to be mutable within the scope of
        // its computation not outside of it. In order to do that we 
        // need to bring in `total` variable into the scope of `for` 
        // loop but then we won't be able to return result
        // and our logic will fail.
        
        // other point is that, to perform total we are relying on
        // an external variable. This creates dependency and since 
        // its a mutable object, if its value is updated before 
        // reaching this point of the code, we would get the wrong
        // result, making this logic hard to trust for correctness.
  }

  //  ... after lots of loc[line of code] ...

  // the role of `total` variable has ended up already 
  // but since its available for access we can might face accidental 
  // updations. example: 
  
  total += 23 

  // suppose an accidental access to the variable has happened
  // someone other then you, gets the access of the variable and 
  // create a feature or fixed a bug using it, now there is
  // multiple point to access/update on your logic variable.
  // this will directly impact code maintenance and also create
  // hard dependencies/coupling because you don't know how deep that
  // variable is rooted inside of that code.

  println(total) // output : 68
  
  // you would be wasting lots of time ⏰ in figuring out source of bugs
  // desperately relying on 🕵🏻‍ the debugger and feeling frustrated.💆🏻
Kotlin | Accumulator limitations

The issue you see is part of the imperative style of programming, you need to be extra careful in terms of visibility and scoping while designing your APIs using OOPs concept , let’s try to fix our pain points.

Disclaimer : it is not a deep dive or history lesson for fold or reduce operations, please refer to Kotlin docs for detailed information.

Fold Operation: [docs] 🚙

It’s one of the functional implementation of accumulator pattern in functional style. Let see the function signature and the let's break it down :


inline fun <T, R> Iterable<T>.fold(
    initial: R, 
    operation: (acc: R, T) -> R
): R
Kotlin | fold
If you want me to cover  lambdas and inline or any other topic, submit the feedback in form below.

The extension is formed on many receivers, you can refer docs for all supported types.

Let’s focus on what it says :

  • Fold extension takes two parameters, first is the initial value and second is a lambda called operation.
  • lambda is invoked on each iteration.
  • Iteration starts from first item to the last i.e from left to right.
  • lambda has 2 parameters, acc:R which is accumulator and T is item of current iteration.
  • lambda always return R i.e the accumulator
  • And the entire fold extension returns R type i.e the final Result of the accumulation or we can say the last value of Accumulator which is returned by the lambda


So according to this, the result of computation is returned by lambda, and that result on its final step is returned to the receiving variable. My lambda returns my local scoped computation. That is a lot of power! We have to achieve closed controlled mutation.


Now we can transform above example into :


 val total = listOf(1,2,3,4,5,6,7,8,9)
    .fold(0){ acc , item-> 
      var sum = acc + item    
      // pass 1 : sum = 0 + 1
      // pass 2 : sum = 1 + 2
      // pass 3 : sum = 3 + 3
      // pass 4 : sum = 6 + 4
      // pass 5 : sum = 10 + 5
      // and so on...
      return@fold sum
  }
  
  println(total) 
  //output : 45

// see now accumulator Variable total is 
// immutable/read only, therefore, no accidental
// update.

// moreover my compuation now have a scope if
// it gives a bug then area to navigate for
// logic is a lot narrow! 
Kotlin | fold example

Reduce Operation : [Docs] 🚗

Same as fold, It’s one of the functional implementation of accumulator pattern in functional style. Let’s see its signature :


inline fun <S, T : S> Iterable<T>.reduce(
    operation: (acc: S, T) -> S
): S
kotlin | reduce

The extension is formed on many receivers, you can refer docs for all supported types.

Let’s focus on what it says :

  • Reduce extension takes only one parameter, that is a lambda  called operation.
  • lambda is invoked on each iteration.
  • Iteration starts from first item to the last i.e from left to right.
  • lambda has 2 parameters, acc:R which is accumulator and T is item of that current iteration.
  • lambda always return R i.e the accumulator.
  • And the entire reduce extension returns R type i.e the final Result of the accumulation or we can say, the last value of Accumulator which is returned by the lambda.

Using reduce, the above example would become :


val total = listOf(1,2,3,4,5,6,7,8,9)
    .reduce{ acc , item-> 
      var sum = acc + item    
      // pass 1 : sum = 1 + 2
      // pass 2 : sum = 3 + 3
      // pass 3 : sum = 6 + 4
      // pass 4 : sum = 10 + 5
      // pass 5 : sum = 15 + 6
      // and so on...
      return@reduce sum
  }
  
  println(total) 
  // output: 45
Kotlin | reduce example

So both of them helps you to break out imperative style of coding, greatly improves accumulator pattern and also introduce immutability in your code.

But now, if both, fold and reduce serves the purpose, which one should you use?

Fold 🆚 Reduce

The difference between both of these functions is that,  fold() takes a default value and uses it as the first step of the accumulator, whereas reduce() uses the first item of iteration as the first step of the accumulator.


  // You can't reduce an empty collection
  
  val items = listOf<Int>() 
  val total = items.reduce{acc,it->acc+it} 
  // Fatal : java.lang.UnsupportedOperationException:
  // Empty collection can't be reduced.
  
  // prefer fold over reduce when you know collection could be empty
  val items = listOf<Int>() 
  val total = items.fold(0){acc,it->acc+it} // output : 0 

  //OR
  
  //like always kotlin have `getOrNull` types extensions for most of
  //exception throwing functions
  val items = listOf<Int>() 
  val total = items.reduceOrNull{acc,it->acc+it} ?: -1 // output : -1

Kotlin | reduce vs fold

One more is thing that you can control is the return type of an object that is received from the operation. For instance :


   val values = listOf(1,2,3,4,5,6,7,8,9)
   val doublesOfValue = values.fold(mutableListOf<Int>()){acc,it-> 
       acc.add(it*2)
       return@fold acc
    }
    // output : [2, 4, 6, 8, 10, 12, 14, 16, 18]
    // we don't have such flexibility with reduce.
    
    // Note : this is different than map operation , which we 
    // will discover in later posts. stay connected!
    
kotlin | fold change return type

If we operate only on a non-empty collection and combine all elements into a single result of the same type, then reduce() is a good choice. On the other hand, if we want to work on a default value or change the result type of the operation, then fold() gives us the flexibility to do that!.

Conclusion 💆🏻‍♀️

So, we are done, now we understood accumulator pattern and how fold() and reduce() are better ways to implement it. It could also be your first step to functional programming, own it slowly and grow your arsenal.

That's all for today 💻! see ya again in next article. Peace!✌


Enjoy the article?

a clap is much appreciated if you enjoyed. No sign up or cost associated :)



Chetan gupta

Hi there! call me Ch8n, I'm a mobile technology enthusiast! love Android #kotlinAlltheWay, CodingMantra: #cleanCoder #TDD #SOLID #designpatterns

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.