# Imperative to functional

Transitioning the mindset

Artūras Šlajus

arturas@tinylabproductions.com

@arturaz_

# Why FP?

• to make programming easier
• by reducing number of bugs
• by making you use your brain less
• by reusing code rather than reimplementing it

# Referential transparency

``````// f(x, y) = x + y * x

scala> def f(x: Int, y: Int) = x + y * x
f: (x: Int, y: Int)Int

scala> f(5, 10)
res0: Int = 55

scala> f(3, 4)
res1: Int = 15``````

# Equational reasoning

Substitution of function call by its returned value.

``````// f(5, 10) = 55; f(3, 4) = 15

scala> val program1 = f(5, 10) + f(3, 4)
program1: Int = 70

scala> val program2 = 55 + 15
program2: Int = 70

scala> val program3 = 70
program3: Int = 70``````

# Now with side effects

We cannot substitute returned values and have the same program.

``````// scala> :t println (_: String)
// String => Unit

scala> val program1 = {
println("Hello"); println("World")
}
Hello
World
program1: Unit = ()

scala> val program2 = { (); () }
program2: Unit = ()``````

# Context dependency

Code depends not only on arguments, but on position in code as well.

``````scala> var counter = 0
scala> def a = { counter += 1; counter * 2 }
scala> def b = { counter += 2; counter * 3 }

scala> counter = 0; a     // == 2
scala> counter = 0; b     // == 6
scala> counter = 0; 2 + 6 // == 8
scala> counter = 0; a + b // == 11
scala> counter = 0; b + a // == 12``````

## Imperative mindset

• OOP or just data + procedures.
• Mutable variables and data structures.
• Relies on side effects to do things. Return type is usually void.

## Purely functional mindset

• Data + pure functions.
• Immutable variables and data structures.
• Functions do not perform side effects and are fully defined through their type signature.

# Functional Computations

## Mutable

``````class Counter(private[this] var _count: Int) {
def count = _count
def inc(): Unit = _count += 1
def dec(): Unit = _count -= 1
}``````

## Mutable usage

``````object CounterApp extends App {
def makeCount(c: Counter): Vector[Int] = {
val count0  = counter.count
val count1  = { counter.inc(); counter.count }
val count2  = { counter.inc(); counter.count }
val count3  = { counter.dec(); counter.count }
Vector(count0, count1, count2, count3)
}

val counter = new Counter(0)
val counts = makeCount(counter)
println(s"counter=\$counter, counts=\$counts")
}``````

## Immutable

``````case class Counter(count: Int) {
def inc: Counter = copy(count = count + 1)
def dec: Counter = copy(count = count - 1)
}``````

## Immutable usage

``````object CounterApp extends App {
def makeCount(c: Counter): (Counter, Vector[Int]) = {
val c1 = c.inc
val c2 = c1.inc
val c3 = c2.dec
(c3, Vector(c.count, c1.count, c2.count, c3.count))
}

val (currentCounter, counts) = makeCount(Counter(0))
println(s"counter=\$currentCounter, counts=\$counts")
}``````

# Functional IO

``````object FizzBuzz extends App { /* Imperative */
var line = ""
def read() = {
print("Enter a number (done to finish): ")
}

while (line != "done") {
try {
val int = line.toInt
if (int % 3 == 0 && int % 5 == 0) println("fizzbuzz")
else if (int % 3 == 0) println("fizz")
else if (int % 5 == 0) println("buzz")
}
catch {
case _: NumberFormatException =>
println(s"\$line was not a number!")
}

}
}``````

## Functional

``````  class Later[A](private val f: () => A) extends AnyVal {
/* Returns a new Later which will combine this
and l2 when evaluated. */
def flatMap[B](l2: A => Later[B]): Later[B] =
Later { l2(f()).endOfTheUniverse_!() }

/* Just evaluates f. Call at the end of the program. */
def endOfTheUniverse_!(): A = f()
}
object Later {
def apply[A](f: => A): Later[A] = new Later(() => f)
}``````

## Some helpful machinery

``````  def int2answer(i: Int): Option[String] =
if (i % 3 == 0 && i % 5 == 0) Some("fizzbuzz")
else if (i % 3 == 0) Some("fizz")
else if (i % 5 == 0) Some("buzz")
else None``````

## Pure computation

``````  val read: Later[String] = Later {
print("Enter a number (done to finish): ")
}

def line2print(line: String): Later[Unit] = Later {
catch {
case _: NumberFormatException =>
println(s"\$line was not a number!")
}
}``````

## Pure IO

``````object FizzBuzz extends App { /* Functional */
/* ... previous code ... */

lazy val main: Later[Unit] = read.flatMap {
case "done" => Later(())
case line => line2print(line).flatMap(_ => main)
}

main.endOfTheUniverse_!()
}``````

# Real Life Example

## Simple Game Model

• There is a world composed of world objects.
• Asteroids have some resources in them.
• Extractors are built on asteroids and extract resources from them for the player.
• World knows how much resources we've extracted so far and how much resources are left.
• Objects can be added or removed from the world.

# Mutable

## ID counting

``````object IdCounter {
type Id = Int
}
class IdCounter {
private[this] var nextId = 0
def newId() = {
val id = nextId
nextId += 1
id
}
}``````

## World Object trait

``````trait WObject {
val id: IdCounter.Id
}``````

## Asteroid class

``````class Asteroid(
val id: IdCounter.Id, var resources: Int
) extends WObject``````

## Extractor class

``````class Extractor(
val id: IdCounter.Id,
asteroid: Asteroid, extractionRate: Int
) extends WObject {
def extract(): Int = {
val resources =
extractionRate min asteroid.resources
asteroid.resources -= resources
resources
}
}``````

## World class

``````class World {
val objects = mutable.Set.empty[WObject]

def extracted = _extracted
private[this] var _extracted = 0

def resourcesLeft = objects.collect {
case a: Asteroid => a.resources
}.sum

/* ... */``````

## World class

``````  /* ... */

def turnStart(): Int = {
val extracted = objects.collect {
case e: Extractor => e.extract()
}.sum
_extracted += extracted
extracted
}
}``````

## Resource extraction

``````  def extract(world: World): Unit = {
println(s"Resources Left: \${world.resourcesLeft}")
println(
s"Extracted, before: \${world.extracted
}, this turn: \${world.turnStart()
}, after: \${world.extracted}"
)
println(s"Resources Left after extraction: \${
world.resourcesLeft}")
println()
}``````
``````  def main(args: Array[String]): Unit = {
val ids = new IdCounter
val asteroid = new Asteroid(ids.newId(), 10)
val extractor =
new Extractor(ids.newId(), asteroid, 4)

val world = new World

while (world.resourcesLeft > 4) extract(world)
println("!!! Removing asteroid !!!")
world.objects.remove(asteroid)
extract(world)
}``````

# Can you spot it?

``````[info] Running game.mutable.MutableReferences
Resources Left: 10
Extracted, before: 0, this turn: 4, after: 4
Resources Left after extraction: 6

Resources Left: 6
Extracted, before: 4, this turn: 4, after: 8
Resources Left after extraction: 2

!!! Removing asteroid !!!
Resources Left: 0
Extracted, before: 8, this turn: 2, after: 10
Resources Left after extraction: 0
``````

# Functional

## ID counting

``````case class IdCounter(id: IdCounter.Id=0) {
def next = IdCounter(id + 1)
}
object IdCounter {
type Id = Int
}``````

## World Object trait

``````sealed trait WObject {
val id: IdCounter.Id
}``````

## Asteroid class

``````case class Asteroid(
id: IdCounter.Id, resources: Int
) extends WObject {
def +(res: Int) = copy(resources = resources + res)
def -(res: Int) = this + -res
}``````
``````case class Extractor(
id: IdCounter.Id, asteroidId: IdCounter.Id,
extractionRate: Int
) extends WObject {
def extract(world: World): (World, Int) = {
world.find[Asteroid](asteroidId).fold(
(world, 0)
) { asteroid =>
val resources =
extractionRate min asteroid.resources
(
world.updated(asteroid - resources),
resources
)
}
}
}``````
``````object World {
def apply(objects: TraversableOnce[WObject]): World =
objects.foldLeft(World())(_.updated(_))
}
case class World(
objectMap: Map[IdCounter.Id, WObject]=Map.empty,
extracted: Int = 0
) {
def find[A <: WObject : ClassTag](id: IdCounter.Id) =
objectMap.get(id).collect { case a: A => a }

def updated(obj: WObject) =
copy(objectMap = objectMap + (obj.id -> obj))
def remove(id: Id): World =
copy(objectMap = objectMap - id)

/* ... */``````
``````  /* ... */

def resourcesLeft = objects.collect {
case a: Asteroid => a.resources
}.sum

def objects = objectMap.values

/* ... */``````
``````  /* ... */

def turnStart: (World, Int) = {
val (newWorld, totalExtracted) = objects
.collect { case e: Extractor => e }
.foldLeft((this, 0)) {
case ((world, totalExtracted), e) =>
val (newWorld, extracted) = e.extract(world)
(newWorld, totalExtracted + extracted)
}
(
newWorld.copy(
extracted = newWorld.extracted + totalExtracted
),
totalExtracted
)
}
}``````
``````  def extract(world: World): World = {
val (newWorld, extracted) = world.turnStart

println(s"Resources Left: \${world.resourcesLeft}")
println(
s"Extracted, before: \${world.extracted
}, this turn: \$extracted, after: \${
newWorld.extracted}"
)
println(s"Resources Left after extraction: \${
newWorld.resourcesLeft}")
println()
newWorld
}``````
``````  def main(args: Array[String]): Unit = {
val ids = IdCounter()
val asteroid = Asteroid(ids.id, 10)
val extractorIds = ids.next
val extractor =
Extractor(extractorIds.id, asteroid.id, 4)

var world = World(Seq(asteroid, extractor))

while (world.resourcesLeft > 4) world = extract(world)
println("!!! Removing asteroid !!!")
world = world.remove(asteroid.id)
extract(world)
}``````
``````[info] Running game.immutable.FPGame
Resources Left: 10
Extracted, before: 0, this turn: 4, after: 4
Resources Left after extraction: 6

Resources Left: 6
Extracted, before: 4, this turn: 4, after: 8
Resources Left after extraction: 2

!!! Removing asteroid !!!
Resources Left: 0
Extracted, before: 8, this turn: 0, after: 8
Resources Left after extraction: 0
``````

# Counter

``````case class Counter(count: Int)

object Counter {
def doAndGet(f: Counter => Counter) =
// State[S, A] is an abstraction over S => (S, A)
State { (c: Counter) =>
val nc = f(c)
(nc, nc.count)
}
val count = State.gets((_: Counter).count)
val inc = doAndGet(c => c.copy(count = c.count + 1))
val dec = doAndGet(c => c.copy(count = c.count - 1))
}``````

## Usage

``````object CounterApp extends App {
val makeCount = Vector(
Counter.count, Counter.inc, Counter.inc,
Counter.dec
).sequenceU
val (counter, counts) = makeCount(Counter(0))
println(s"counter=\$counter, counts=\$counts")
}``````

# FizzBuzz

``````object FizzBuzz extends SafeApp { /* Scalaz */
def int2answer(i: Int): Option[String] =
if (i % 3 == 0 && i % 5 == 0) Some("fizzbuzz")
else if (i % 3 == 0) Some("fizz")
else if (i % 5 == 0) Some("buzz")
else None

val read: IO[String] = for {
_ <- IO.putStr("Enter a number (done to finish): ")
} yield line

def line2print(line: String): IO[Unit] = parseInt(line).fold(
_ => IO.putStrLn(s"\$line was not a number!"),
)

override def runc: IO[Unit] = {
lazy val main: IO[Unit] = for {
_ <- if (line == "done") IO.ioUnit
else line2print(line) flatMap (_ => main)
} yield ()

main
}
}``````

# Thank you

Artūras Šlajus

arturas@tinylabproductions.com

@arturaz_

#### Imperative to FP to Scalaz - transitioning the mindset

By Artūras Šlajus

### Imperative to FP to Scalaz - transitioning the mindset

We'll be looking at several simple programs and their implementations in imperative, purely functional and purely functional done with scalaz mindsets.

• 1,064