SlideShare a Scribd company logo
Functional
Programming 101 with
Scala and ZIO
Functional World
April 15th, 2021
Jorge Vásquez
Scala Developer
@Scalac
Agenda
Agenda
• Functional Programming (FP)
basic concepts
Agenda
• Functional Programming (FP)
basic concepts
• ZIO basic concepts
Agenda
• Functional Programming (FP)
basic concepts
• ZIO basic concepts
• Live coding: Tic-Tac-Toe game
What is Functional
Programming?
What is Functional Programming?
Programming paradigm, where programs are a
composition of pure functions
Characteristics of a
Pure Function
Characteristics of a
Pure Function
• Total
Characteristics of a
Pure Function
• Total
• Deterministic and depends on its
inputs only
Characteristics of a
Pure Function
• Total
• Deterministic and depends on its
inputs only
• Must not have side effects
A Pure Function must be Total
For each input that is provided to the function there must
be a defined output
A Pure Function must be Total
def divide(a: Int, b: Int): Int = a / b
divide(5, 0)
// java.lang.ArithmeticException: / by zero
A Pure Function must be Total
def divide(a: Int, b: Int): Int = a / b
divide(5, 0)
// java.lang.ArithmeticException: / by zero
A Pure Function must be Total
def divide(a: Int, b: Int): Int = a / b
divide(5, 0)
// java.lang.ArithmeticException: / by zero
A Pure Function must be Total
def divide(a: Int, b: Int): Int = a / b
divide(5, 0)
// java.lang.ArithmeticException: / by zero
A Pure Function must be Total
def divide(a: Int, b: Int): Int = a / b
A Pure Function must be Total
def divide(a: Int, b: Int): Int = a / b
• The signature of this function tells a lie!
A Pure Function must be Total
def divide(a: Int, b: Int): Int = a / b
• The signature of this function tells a lie!
• Every time we call it we will have to be very careful
A Pure Function must be Total
def divide(a: Int, b: Int): Int = a / b
• The signature of this function tells a lie!
• Every time we call it we will have to be very careful
• Runtime exceptions can happen. The compiler is not
able to do anything to help us to avoid this
A Pure Function must be Total
def divide(a: Int, b: Int): Option[Int] =
if (b != 0) Some(a / b) else None
divide(5, 0)
// None
A Pure Function must be Total
def divide(a: Int, b: Int): Option[Int] =
if (b != 0) Some(a / b) else None
divide(5, 0)
// None
A Pure Function must be Total
def divide(a: Int, b: Int): Option[Int] =
if (b != 0) Some(a / b) else None
divide(5, 0)
// None
A Pure Function must be Total
def divide(a: Int, b: Int): Option[Int] =
if (b != 0) Some(a / b) else None
divide(5, 0)
// None
A Pure Function must be Total
def divide(a: Int, b: Int): Option[Int] =
if (b != 0) Some(a / b) else None
A Pure Function must be Total
def divide(a: Int, b: Int): Option[Int] =
if (b != 0) Some(a / b) else None
• The function’s signature clearly communicates that some
inputs are not handled
A Pure Function must be Total
def divide(a: Int, b: Int): Option[Int] =
if (b != 0) Some(a / b) else None
• The function’s signature clearly communicates that some
inputs are not handled
• The compiler will force us to consider the case in which the
result is not defined
A Pure Function must be Total
def divide(a: Int, b: Int): Option[Int] =
if (b != 0) Some(a / b) else None
• The function’s signature clearly communicates that some
inputs are not handled
• The compiler will force us to consider the case in which the
result is not defined
• No runtime exceptions!
A Pure Function must be Deterministic
and depend only on its inputs
For each input that is provided to the function, the same
output must be returned, no matter how many times the
function is called
A Pure Function must be Deterministic
and depend only on its inputs
def generateRandomInt(): Int = (new scala.util.Random).nextInt
generateRandomInt() // Result: -272770531
generateRandomInt() // Result: 217937820
A Pure Function must be Deterministic
and depend only on its inputs
def generateRandomInt(): Int = (new scala.util.Random).nextInt
generateRandomInt() // Result: -272770531
generateRandomInt() // Result: 217937820
A Pure Function must be Deterministic
and depend only on its inputs
def generateRandomInt(): Int = (new scala.util.Random).nextInt
generateRandomInt() // Result: -272770531
generateRandomInt() // Result: 217937820
A Pure Function must be Deterministic
and depend only on its inputs
def generateRandomInt(): Int = (new scala.util.Random).nextInt
generateRandomInt() // Result: -272770531
generateRandomInt() // Result: 217937820
A Pure Function must be Deterministic
and depend only on its inputs
def generateRandomInt(): Int = (new scala.util.Random).nextInt
A Pure Function must be Deterministic
and depend only on its inputs
def generateRandomInt(): Int = (new scala.util.Random).nextInt
• Clearly not deterministic!
A Pure Function must be Deterministic
and depend only on its inputs
def generateRandomInt(): Int = (new scala.util.Random).nextInt
• Clearly not deterministic!
• The signature is misleading, because there is a hidden
dependency on a scala.util.Random object
A Pure Function must be Deterministic
and depend only on its inputs
def generateRandomInt(): Int = (new scala.util.Random).nextInt
• Clearly not deterministic!
• The signature is misleading, because there is a hidden
dependency on a scala.util.Random object
• Difficult to test because we can never really be sure how the
function will behave
A Pure Function must be Deterministic
and depend only on its inputs
final case class RNG(seed: Long) {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = RNG(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
}
def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt
val random = RNG(10)
val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181)
val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181)
val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
A Pure Function must be Deterministic
and depend only on its inputs
final case class RNG(seed: Long) {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = RNG(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
}
def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt
val random = RNG(10)
val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181)
val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181)
val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
A Pure Function must be Deterministic
and depend only on its inputs
final case class RNG(seed: Long) {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = RNG(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
}
def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt
val random = RNG(10)
val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181)
val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181)
val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
A Pure Function must be Deterministic
and depend only on its inputs
final case class RNG(seed: Long) {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = RNG(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
}
def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt
val random = RNG(10)
val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181)
val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181)
val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
A Pure Function must be Deterministic
and depend only on its inputs
final case class RNG(seed: Long) {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = RNG(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
}
def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt
val random = RNG(10)
val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181)
val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181)
val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
A Pure Function must be Deterministic
and depend only on its inputs
final case class RNG(seed: Long) {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = RNG(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
}
def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt
val random = RNG(10)
val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181)
val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181)
val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
A Pure Function must not have side
effects
Finally, a function must not have any side effects:
A Pure Function must not have side
effects
Finally, a function must not have any side effects:
• Memory mutations
A Pure Function must not have side
effects
Finally, a function must not have any side effects:
• Memory mutations
• Interactions with the outside world, such as:
A Pure Function must not have side
effects
Finally, a function must not have any side effects:
• Memory mutations
• Interactions with the outside world, such as:
• Printing messages to the console
A Pure Function must not have side
effects
Finally, a function must not have any side effects:
• Memory mutations
• Interactions with the outside world, such as:
• Printing messages to the console
• Calling an external API
A Pure Function must not have side
effects
Finally, a function must not have any side effects:
• Memory mutations
• Interactions with the outside world, such as:
• Printing messages to the console
• Calling an external API
• Querying a database
A Pure Function must not have side
effects
A pure function can only:
A Pure Function must not have side
effects
A pure function can only:
• Work with immutable values
A Pure Function must not have side
effects
A pure function can only:
• Work with immutable values
• Return an output for a corresponding input
A Pure Function must not have side
effects
var a = 0
def increment(inc: Int): Int = {
a + = inc
a
}
A Pure Function must not have side
effects
def add(a: Int, b: Int): Int = {
println(s "Adding two integers: $a and $b")
a + b
}
FP vs. OOP
FP vs. OOP
• Variables: Immutable / Mutable
FP vs. OOP
• Variables: Immutable / Mutable
• Side effects: NO / YES
FP vs. OOP
• Variables: Immutable / Mutable
• Side effects: NO / YES
• Iterations: Recursion / Loops
FP vs. OOP
FP vs. OOP
• State: Flows through pure
functions / Shared by several
objects
FP vs. OOP
• State: Flows through pure
functions / Shared by several
objects
• Key elements: Immutable values
and Functions / Objects and
Methods
FP vs. OOP
• State: Flows through pure
functions / Shared by several
objects
• Key elements: Immutable values
and Functions / Objects and
Methods
• Suitable for Parallel
programming: YES / Not so
much
Benefits of
Functional
Programming
Benefits of
Functional
Programming
• Local reasoning
Benefits of
Functional
Programming
• Local reasoning
• Referential transparency ->
Fearless refactoring!
Benefits of
Functional
Programming
• Local reasoning
• Referential transparency ->
Fearless refactoring!
• Conciseness -> Fewer bugs!
Benefits of
Functional
Programming
Benefits of
Functional
Programming
• Easier to test
Benefits of
Functional
Programming
• Easier to test
• Applications behave more
predictably
Benefits of
Functional
Programming
• Easier to test
• Applications behave more
predictably
• Allows us to write correct parallel
programs
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Effects
Functional Effects
• Descriptions of interactions with
the outside world
Functional Effects
• Descriptions of interactions with
the outside world
• Immutable values that can serve
as inputs and outputs of pure
functions
Functional Effects
• Descriptions of interactions with
the outside world
• Immutable values that can serve
as inputs and outputs of pure
functions
• They are executed only at the
End of the World
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Enter ZIO!
ZIO - The Library
Allows us to build modern applications, using the
principles of Functional Programming!
ZIO - The Library
ZIO - The Library
• Asynchronous & Concurrent -> Fiber-based model!
ZIO - The Library
• Asynchronous & Concurrent -> Fiber-based model!
• Resilient -> Leverages the power of Scala's Type System!
ZIO - The Library
• Asynchronous & Concurrent -> Fiber-based model!
• Resilient -> Leverages the power of Scala's Type System!
• Efficient -> Apps that never leak resources!
ZIO - The Library
• Asynchronous & Concurrent -> Fiber-based model!
• Resilient -> Leverages the power of Scala's Type System!
• Efficient -> Apps that never leak resources!
• Easy to understand and test -> Thanks to superior
composability!
ZIO - The Data Type
ZIO[-R, +E, +A]
ZIO - The Data Type
ZIO[-R, +E, +A]
• Core type of the ZIO Library
ZIO - The Data Type
ZIO[-R, +E, +A]
• Core type of the ZIO Library
• Functional Effect
ZIO - The Data Type
A good mental model is the following:
R => Either[E, A]
This means that a ZIO effect:
ZIO - The Data Type
A good mental model is the following:
R => Either[E, A]
This means that a ZIO effect:
• Needs an environment of type R to run
ZIO - The Data Type
A good mental model is the following:
R => Either[E, A]
This means that a ZIO effect:
• Needs an environment of type R to run
• It may fail with an error of type E
ZIO - The Data Type
A good mental model is the following:
R => Either[E, A]
This means that a ZIO effect:
• Needs an environment of type R to run
• It may fail with an error of type E
• Or it may complete successfully, returning a value of type A
ZIO - The Data Type
Common aliases:
Task[+A] = ZIO[Any, Throwable, +A]
UIO[+A] = ZIO[Any, Nothing, +A]
RIO[-R, +A] = ZIO[-R, Throwable, +A]
IO[+E, +A] = ZIO[Any, E, A]
URIO[-R, +A] = ZIO[R, Nothing, A]
Live coding
Tic-Tac-Toe game with ZIO!
https://github.com/jorge-vasquez-2301/zio-tictactoe
Where to learn more
• Introduction to Programming with ZIO Functional Effects - Scalac Blog
• Introducción a la Programación con Efectos Funcionales usando ZIO -
Scalac Blog
• Mastering modularity in ZIO with ZLayer - Scalac Blog
• How to write a (completely lock-free) concurrent LRU Cache with ZIO STM
• ZIO Official Site
• Zionomicon
Where to learn more
Learn how to use the full potential of Functional
Programming with Scalac Trainings!
• Scala 2 for Java Developers
• Scala 3 for Scala 2 Developers
• ZIO
We are hiring!
https://scalac.io/careers/
@majakryzan
maja.kryzan@scalac.io
Contact me
@jorvasquez2301
jorge-vasquez-2301
jorge.vasquez@scalac.io

More Related Content

PDF
ZIO-Direct - Functional Scala 2022
PPTX
ZIO: Powerful and Principled Functional Programming in Scala
PDF
A Prelude of Purity: Scaling Back ZIO
PDF
The aggregate function - from sequential and parallel folds to parallel aggre...
PPTX
Quill vs Slick Smackdown
PDF
Exploring ZIO Prelude: The game changer for typeclasses in Scala
PPTX
Purely Functional Data Structures in Scala
PDF
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
ZIO-Direct - Functional Scala 2022
ZIO: Powerful and Principled Functional Programming in Scala
A Prelude of Purity: Scaling Back ZIO
The aggregate function - from sequential and parallel folds to parallel aggre...
Quill vs Slick Smackdown
Exploring ZIO Prelude: The game changer for typeclasses in Scala
Purely Functional Data Structures in Scala
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...

What's hot (20)

PDF
The Functional Programming Triad of Map, Filter and Fold
PDF
Error Management: Future vs ZIO
PDF
Scala categorytheory
PDF
ZIO Queue
PDF
Refactoring Functional Type Classes
PDF
Sequence and Traverse - Part 1
PDF
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
PDF
Zio in real world
PDF
‘go-to’ general-purpose sequential collections - from Java To Scala
PDF
An introduction to Rust: the modern programming language to develop safe and ...
PDF
Be Smart, Constrain Your Types to Free Your Brain!
PPTX
Presentation on function
PDF
Collections In Java
PDF
Contravariant functors in scala
PDF
Traversals for all ocasions
PPTX
java 8 new features
PDF
Asynchronous javascript
PDF
Monoids - Part 1 - with examples using Scalaz and Cats
PPTX
Capabilities for Resources and Effects
PPTX
Type script - advanced usage and practices
The Functional Programming Triad of Map, Filter and Fold
Error Management: Future vs ZIO
Scala categorytheory
ZIO Queue
Refactoring Functional Type Classes
Sequence and Traverse - Part 1
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Zio in real world
‘go-to’ general-purpose sequential collections - from Java To Scala
An introduction to Rust: the modern programming language to develop safe and ...
Be Smart, Constrain Your Types to Free Your Brain!
Presentation on function
Collections In Java
Contravariant functors in scala
Traversals for all ocasions
java 8 new features
Asynchronous javascript
Monoids - Part 1 - with examples using Scalaz and Cats
Capabilities for Resources and Effects
Type script - advanced usage and practices
Ad

Similar to Functional Programming 101 with Scala and ZIO @FunctionalWorld (20)

PDF
pure-functional-programming.pdf
PPTX
Functional programming
PPTX
Intro to Functional Programming
PDF
Functional Operations - Susan Potter
PDF
Gentle Introduction to Scala
PDF
Power of functions in a typed world
PDF
Definitions of Functional Programming
PDF
Scala intro workshop
PPTX
Scala Introduction - Synerzip
PPTX
Introduction to Scala
PDF
Lecture 5: Functional Programming
PPTX
Principles of functional progrmming in scala
PDF
Meet scala
PDF
Introduction to functional programming (In Arabic)
PDF
PDF
Functional Programming In Scala Second Edition Meap V08 2nd All Chapters Avai...
PDF
Functional programming is the most extreme programming
PDF
Scala: A brief tutorial
KEY
Scala: functional programming for the imperative mind
PDF
Probabilistic Programming in Scala
pure-functional-programming.pdf
Functional programming
Intro to Functional Programming
Functional Operations - Susan Potter
Gentle Introduction to Scala
Power of functions in a typed world
Definitions of Functional Programming
Scala intro workshop
Scala Introduction - Synerzip
Introduction to Scala
Lecture 5: Functional Programming
Principles of functional progrmming in scala
Meet scala
Introduction to functional programming (In Arabic)
Functional Programming In Scala Second Edition Meap V08 2nd All Chapters Avai...
Functional programming is the most extreme programming
Scala: A brief tutorial
Scala: functional programming for the imperative mind
Probabilistic Programming in Scala
Ad

More from Jorge Vásquez (7)

PDF
Behold! The Happy Path To Captivate Your Users With Stunning CLI Apps!
PDF
Programación Funcional 101 con Scala y ZIO 2.0
PDF
Consiguiendo superpoderes para construir aplicaciones modernas en la JVM con ZIO
PDF
ZIO Prelude - ZIO World 2021
PDF
Exploring type level programming in Scala
PDF
The Terror-Free Guide to Introducing Functional Scala at Work
PDF
Introduction to programming with ZIO functional effects
Behold! The Happy Path To Captivate Your Users With Stunning CLI Apps!
Programación Funcional 101 con Scala y ZIO 2.0
Consiguiendo superpoderes para construir aplicaciones modernas en la JVM con ZIO
ZIO Prelude - ZIO World 2021
Exploring type level programming in Scala
The Terror-Free Guide to Introducing Functional Scala at Work
Introduction to programming with ZIO functional effects

Recently uploaded (20)

PDF
top salesforce developer skills in 2025.pdf
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
Transform Your Business with a Software ERP System
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PPTX
history of c programming in notes for students .pptx
PDF
Nekopoi APK 2025 free lastest update
PDF
Digital Systems & Binary Numbers (comprehensive )
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Reimagine Home Health with the Power of Agentic AI​
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
System and Network Administraation Chapter 3
PPTX
Computer Software and OS of computer science of grade 11.pptx
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
assetexplorer- product-overview - presentation
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
top salesforce developer skills in 2025.pdf
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Design an Analysis of Algorithms II-SECS-1021-03
Transform Your Business with a Software ERP System
How to Migrate SBCGlobal Email to Yahoo Easily
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
history of c programming in notes for students .pptx
Nekopoi APK 2025 free lastest update
Digital Systems & Binary Numbers (comprehensive )
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Reimagine Home Health with the Power of Agentic AI​
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
How to Choose the Right IT Partner for Your Business in Malaysia
System and Network Administraation Chapter 3
Computer Software and OS of computer science of grade 11.pptx
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
wealthsignaloriginal-com-DS-text-... (1).pdf
assetexplorer- product-overview - presentation
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...

Functional Programming 101 with Scala and ZIO @FunctionalWorld

  • 1. Functional Programming 101 with Scala and ZIO Functional World April 15th, 2021
  • 4. Agenda • Functional Programming (FP) basic concepts
  • 5. Agenda • Functional Programming (FP) basic concepts • ZIO basic concepts
  • 6. Agenda • Functional Programming (FP) basic concepts • ZIO basic concepts • Live coding: Tic-Tac-Toe game
  • 8. What is Functional Programming? Programming paradigm, where programs are a composition of pure functions
  • 10. Characteristics of a Pure Function • Total
  • 11. Characteristics of a Pure Function • Total • Deterministic and depends on its inputs only
  • 12. Characteristics of a Pure Function • Total • Deterministic and depends on its inputs only • Must not have side effects
  • 13. A Pure Function must be Total For each input that is provided to the function there must be a defined output
  • 14. A Pure Function must be Total def divide(a: Int, b: Int): Int = a / b divide(5, 0) // java.lang.ArithmeticException: / by zero
  • 15. A Pure Function must be Total def divide(a: Int, b: Int): Int = a / b divide(5, 0) // java.lang.ArithmeticException: / by zero
  • 16. A Pure Function must be Total def divide(a: Int, b: Int): Int = a / b divide(5, 0) // java.lang.ArithmeticException: / by zero
  • 17. A Pure Function must be Total def divide(a: Int, b: Int): Int = a / b divide(5, 0) // java.lang.ArithmeticException: / by zero
  • 18. A Pure Function must be Total def divide(a: Int, b: Int): Int = a / b
  • 19. A Pure Function must be Total def divide(a: Int, b: Int): Int = a / b • The signature of this function tells a lie!
  • 20. A Pure Function must be Total def divide(a: Int, b: Int): Int = a / b • The signature of this function tells a lie! • Every time we call it we will have to be very careful
  • 21. A Pure Function must be Total def divide(a: Int, b: Int): Int = a / b • The signature of this function tells a lie! • Every time we call it we will have to be very careful • Runtime exceptions can happen. The compiler is not able to do anything to help us to avoid this
  • 22. A Pure Function must be Total def divide(a: Int, b: Int): Option[Int] = if (b != 0) Some(a / b) else None divide(5, 0) // None
  • 23. A Pure Function must be Total def divide(a: Int, b: Int): Option[Int] = if (b != 0) Some(a / b) else None divide(5, 0) // None
  • 24. A Pure Function must be Total def divide(a: Int, b: Int): Option[Int] = if (b != 0) Some(a / b) else None divide(5, 0) // None
  • 25. A Pure Function must be Total def divide(a: Int, b: Int): Option[Int] = if (b != 0) Some(a / b) else None divide(5, 0) // None
  • 26. A Pure Function must be Total def divide(a: Int, b: Int): Option[Int] = if (b != 0) Some(a / b) else None
  • 27. A Pure Function must be Total def divide(a: Int, b: Int): Option[Int] = if (b != 0) Some(a / b) else None • The function’s signature clearly communicates that some inputs are not handled
  • 28. A Pure Function must be Total def divide(a: Int, b: Int): Option[Int] = if (b != 0) Some(a / b) else None • The function’s signature clearly communicates that some inputs are not handled • The compiler will force us to consider the case in which the result is not defined
  • 29. A Pure Function must be Total def divide(a: Int, b: Int): Option[Int] = if (b != 0) Some(a / b) else None • The function’s signature clearly communicates that some inputs are not handled • The compiler will force us to consider the case in which the result is not defined • No runtime exceptions!
  • 30. A Pure Function must be Deterministic and depend only on its inputs For each input that is provided to the function, the same output must be returned, no matter how many times the function is called
  • 31. A Pure Function must be Deterministic and depend only on its inputs def generateRandomInt(): Int = (new scala.util.Random).nextInt generateRandomInt() // Result: -272770531 generateRandomInt() // Result: 217937820
  • 32. A Pure Function must be Deterministic and depend only on its inputs def generateRandomInt(): Int = (new scala.util.Random).nextInt generateRandomInt() // Result: -272770531 generateRandomInt() // Result: 217937820
  • 33. A Pure Function must be Deterministic and depend only on its inputs def generateRandomInt(): Int = (new scala.util.Random).nextInt generateRandomInt() // Result: -272770531 generateRandomInt() // Result: 217937820
  • 34. A Pure Function must be Deterministic and depend only on its inputs def generateRandomInt(): Int = (new scala.util.Random).nextInt generateRandomInt() // Result: -272770531 generateRandomInt() // Result: 217937820
  • 35. A Pure Function must be Deterministic and depend only on its inputs def generateRandomInt(): Int = (new scala.util.Random).nextInt
  • 36. A Pure Function must be Deterministic and depend only on its inputs def generateRandomInt(): Int = (new scala.util.Random).nextInt • Clearly not deterministic!
  • 37. A Pure Function must be Deterministic and depend only on its inputs def generateRandomInt(): Int = (new scala.util.Random).nextInt • Clearly not deterministic! • The signature is misleading, because there is a hidden dependency on a scala.util.Random object
  • 38. A Pure Function must be Deterministic and depend only on its inputs def generateRandomInt(): Int = (new scala.util.Random).nextInt • Clearly not deterministic! • The signature is misleading, because there is a hidden dependency on a scala.util.Random object • Difficult to test because we can never really be sure how the function will behave
  • 39. A Pure Function must be Deterministic and depend only on its inputs final case class RNG(seed: Long) { def nextInt: (Int, RNG) = { val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL val nextRNG = RNG(newSeed) val n = (newSeed >>> 16).toInt (n, nextRNG) } } def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt val random = RNG(10) val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181) val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181) val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
  • 40. A Pure Function must be Deterministic and depend only on its inputs final case class RNG(seed: Long) { def nextInt: (Int, RNG) = { val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL val nextRNG = RNG(newSeed) val n = (newSeed >>> 16).toInt (n, nextRNG) } } def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt val random = RNG(10) val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181) val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181) val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
  • 41. A Pure Function must be Deterministic and depend only on its inputs final case class RNG(seed: Long) { def nextInt: (Int, RNG) = { val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL val nextRNG = RNG(newSeed) val n = (newSeed >>> 16).toInt (n, nextRNG) } } def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt val random = RNG(10) val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181) val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181) val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
  • 42. A Pure Function must be Deterministic and depend only on its inputs final case class RNG(seed: Long) { def nextInt: (Int, RNG) = { val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL val nextRNG = RNG(newSeed) val n = (newSeed >>> 16).toInt (n, nextRNG) } } def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt val random = RNG(10) val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181) val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181) val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
  • 43. A Pure Function must be Deterministic and depend only on its inputs final case class RNG(seed: Long) { def nextInt: (Int, RNG) = { val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL val nextRNG = RNG(newSeed) val n = (newSeed >>> 16).toInt (n, nextRNG) } } def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt val random = RNG(10) val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181) val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181) val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
  • 44. A Pure Function must be Deterministic and depend only on its inputs final case class RNG(seed: Long) { def nextInt: (Int, RNG) = { val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL val nextRNG = RNG(newSeed) val n = (newSeed >>> 16).toInt (n, nextRNG) } } def generateRandomInt(random: RNG): (Int, RNG) = random.nextInt val random = RNG(10) val (n1, random1) = generateRandomInt(random) // n1 = 3847489, random1 = RNG(252149039181) val (n2, random2) = generateRandomInt(random) // n2 = 3847489, random2 = RNG(252149039181) val (n3, random3) = generateRandomInt(random2) // n3 = 1334288366, random3 = RNG(87443922374356)
  • 45. A Pure Function must not have side effects Finally, a function must not have any side effects:
  • 46. A Pure Function must not have side effects Finally, a function must not have any side effects: • Memory mutations
  • 47. A Pure Function must not have side effects Finally, a function must not have any side effects: • Memory mutations • Interactions with the outside world, such as:
  • 48. A Pure Function must not have side effects Finally, a function must not have any side effects: • Memory mutations • Interactions with the outside world, such as: • Printing messages to the console
  • 49. A Pure Function must not have side effects Finally, a function must not have any side effects: • Memory mutations • Interactions with the outside world, such as: • Printing messages to the console • Calling an external API
  • 50. A Pure Function must not have side effects Finally, a function must not have any side effects: • Memory mutations • Interactions with the outside world, such as: • Printing messages to the console • Calling an external API • Querying a database
  • 51. A Pure Function must not have side effects A pure function can only:
  • 52. A Pure Function must not have side effects A pure function can only: • Work with immutable values
  • 53. A Pure Function must not have side effects A pure function can only: • Work with immutable values • Return an output for a corresponding input
  • 54. A Pure Function must not have side effects var a = 0 def increment(inc: Int): Int = { a + = inc a }
  • 55. A Pure Function must not have side effects def add(a: Int, b: Int): Int = { println(s "Adding two integers: $a and $b") a + b }
  • 57. FP vs. OOP • Variables: Immutable / Mutable
  • 58. FP vs. OOP • Variables: Immutable / Mutable • Side effects: NO / YES
  • 59. FP vs. OOP • Variables: Immutable / Mutable • Side effects: NO / YES • Iterations: Recursion / Loops
  • 61. FP vs. OOP • State: Flows through pure functions / Shared by several objects
  • 62. FP vs. OOP • State: Flows through pure functions / Shared by several objects • Key elements: Immutable values and Functions / Objects and Methods
  • 63. FP vs. OOP • State: Flows through pure functions / Shared by several objects • Key elements: Immutable values and Functions / Objects and Methods • Suitable for Parallel programming: YES / Not so much
  • 66. Benefits of Functional Programming • Local reasoning • Referential transparency -> Fearless refactoring!
  • 67. Benefits of Functional Programming • Local reasoning • Referential transparency -> Fearless refactoring! • Conciseness -> Fewer bugs!
  • 70. Benefits of Functional Programming • Easier to test • Applications behave more predictably
  • 71. Benefits of Functional Programming • Easier to test • Applications behave more predictably • Allows us to write correct parallel programs
  • 75. Functional Effects • Descriptions of interactions with the outside world
  • 76. Functional Effects • Descriptions of interactions with the outside world • Immutable values that can serve as inputs and outputs of pure functions
  • 77. Functional Effects • Descriptions of interactions with the outside world • Immutable values that can serve as inputs and outputs of pure functions • They are executed only at the End of the World
  • 80. ZIO - The Library Allows us to build modern applications, using the principles of Functional Programming!
  • 81. ZIO - The Library
  • 82. ZIO - The Library • Asynchronous & Concurrent -> Fiber-based model!
  • 83. ZIO - The Library • Asynchronous & Concurrent -> Fiber-based model! • Resilient -> Leverages the power of Scala's Type System!
  • 84. ZIO - The Library • Asynchronous & Concurrent -> Fiber-based model! • Resilient -> Leverages the power of Scala's Type System! • Efficient -> Apps that never leak resources!
  • 85. ZIO - The Library • Asynchronous & Concurrent -> Fiber-based model! • Resilient -> Leverages the power of Scala's Type System! • Efficient -> Apps that never leak resources! • Easy to understand and test -> Thanks to superior composability!
  • 86. ZIO - The Data Type ZIO[-R, +E, +A]
  • 87. ZIO - The Data Type ZIO[-R, +E, +A] • Core type of the ZIO Library
  • 88. ZIO - The Data Type ZIO[-R, +E, +A] • Core type of the ZIO Library • Functional Effect
  • 89. ZIO - The Data Type A good mental model is the following: R => Either[E, A] This means that a ZIO effect:
  • 90. ZIO - The Data Type A good mental model is the following: R => Either[E, A] This means that a ZIO effect: • Needs an environment of type R to run
  • 91. ZIO - The Data Type A good mental model is the following: R => Either[E, A] This means that a ZIO effect: • Needs an environment of type R to run • It may fail with an error of type E
  • 92. ZIO - The Data Type A good mental model is the following: R => Either[E, A] This means that a ZIO effect: • Needs an environment of type R to run • It may fail with an error of type E • Or it may complete successfully, returning a value of type A
  • 93. ZIO - The Data Type Common aliases: Task[+A] = ZIO[Any, Throwable, +A] UIO[+A] = ZIO[Any, Nothing, +A] RIO[-R, +A] = ZIO[-R, Throwable, +A] IO[+E, +A] = ZIO[Any, E, A] URIO[-R, +A] = ZIO[R, Nothing, A]
  • 94. Live coding Tic-Tac-Toe game with ZIO! https://github.com/jorge-vasquez-2301/zio-tictactoe
  • 95. Where to learn more • Introduction to Programming with ZIO Functional Effects - Scalac Blog • Introducción a la Programación con Efectos Funcionales usando ZIO - Scalac Blog • Mastering modularity in ZIO with ZLayer - Scalac Blog • How to write a (completely lock-free) concurrent LRU Cache with ZIO STM • ZIO Official Site • Zionomicon
  • 96. Where to learn more Learn how to use the full potential of Functional Programming with Scalac Trainings! • Scala 2 for Java Developers • Scala 3 for Scala 2 Developers • ZIO