12. PART 1
PART 1
PART 1
FP
FP
FP
FUNCTIONAL PROPAGANDA
also known as
also known as
also known as Functional Programming
Functional Programming
Functional Programming
19. Two hours after deployment
Two hours after deployment
Two hours after deployment
20. 1999 I switched from C++ to Java
1999 I switched from C++ to Java
1999 I switched from C++ to Java
Life is too short for malloc
Life is too short for malloc
Life is too short for malloc
21. 2016 - slowly leaving Java away
2016 - slowly leaving Java away
2016 - slowly leaving Java away
I am too old to mutate
I am too old to mutate
I am too old to mutate
22. What is functional programming?
What is functional programming?
What is functional programming?
Programming with functions:
Programming with functions:
Programming with functions:
deterministic
total
pure
23. What is functional programming?
What is functional programming?
What is functional programming?
Programming with functions:
Programming with functions:
Programming with functions:
deterministic
total
pure
Ok, I have no idea. Just copied this de nition
Ok, I have no idea. Just copied this de nition
Ok, I have no idea. Just copied this de nition
from John De Goes ;-)
from John De Goes ;-)
from John De Goes ;-)
24. DETERMINISTIC
depend on arguments only
always yield same results for the same
arguments
fun hello() = "Hello Jug"
fun fact(n:Int) = if (n<=1) 1 else n*fact(n-1)
fun radom() = Math.random()*0.7
25. TOTAL:
Yields result/ nishes for all possible arguments
Yields result/ nishes for all possible arguments
Yields result/ nishes for all possible arguments
fun negate(a:Int):Int = -a
fun radomize(v:String) = "Radom znowu $v"
fun parseInt(t:String):Int = /* whatever */
26. PURE:
Leaves no traces. The only (practical) way to
Leaves no traces. The only (practical) way to
Leaves no traces. The only (practical) way to
detect the function was called is by reading a
detect the function was called is by reading a
detect the function was called is by reading a
result.
result.
result.
fun add(a:Int, b:Int) = a+b
[CODE A]
val x = add(6,3) [OR] val x = 9
[CODE B]
27. fun add(a:Int, b:Int) = a*b //happy debugging
fun add2(a:Int, b:Int) = run {
Thread.sleep(a*1000)
Thread.sleep(b*1000)
return a+b
}
fun add3(a:Int, b:Int) = (a+b).also {
log("was adding something in Kielce")
}
28. Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
29. Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
COMPOSABILITY
COMPOSABILITY
COMPOSABILITY
30. PART 2
PART 2
PART 2
KOTLIN PROPAGANDA
KOTLIN PROPAGANDA
KOTLIN PROPAGANDA
33. Data class
Data class
Data class
kotlin
kotlin
kotlin
data class Person(
val name:String,
val age:Int,
val drinking:Boolean = true
)
34. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this name = name;
35. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this name = name;
val drinking:Boolean = true
val drinking:Boolean = true
val drinking:Boolean = true
36. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this name = name;
37. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this name = name;
equals and hashCode
equals and hashCode
equals and hashCode
38. public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name)
&& this.age == var2.age
&& this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
39. public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name)
&& this.age == var2.age
&& this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
41. fun main() = run {
val p = Person("irek", 27, true)
//
}
42. fun main() = run {
val p = Person("irek", 27, true)
val p1 = p.copy(name = "Irek")
println(p) //Person(name=irek, age=27, drinking=true)
println(p1) //Person(name=Irek, age=27, drinking=true)
}
43. fun main() = run {
val p = Person("irek", 27, true)
val p1 = p.copy(name = "Irek")
val p2 = p1.copy(age = 28)
val p3 = p2.copy(drinking = false)
val p4 = p3.copy(age = 29, drinking = true)
val p5 = p4.copy(name = "Zdzich", age = p4.age+1, drinking = fals
println(p5)
}
//Person(name=Zdzich, age=30, drinking=false)
44. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
45. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", drinking=" + this.drinking + ")";
}
@NotNull
public final Person copy(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, drinking);
}
@NotNull
public final Person copy(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this age, this drinking);
46. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", drinking=" + this.drinking + ")";
}
@NotNull
public final Person copy(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, drinking);
}
@NotNull
public final Person copy(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this age, this drinking);
almost
almost
almost
47. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", drinking=" + this.drinking + ")";
}
@NotNull
public final Person copy(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, drinking);
}
@NotNull
public final Person copy(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this.age, this.drinking);
}
@NotNull
public final Person copy(int age) {
return new Person(this.name, age, this.drinking);
}
@NotNull
public final Person copy(boolean drinking) {
return new Person(this.name, this.age, drinking);
}
@NotNull
public final Person copy(@NotNull String name, int age) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, this.drinking);
}
@NotNull
public final Person copy(@NotNull String name, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this.age, drinking);
}
@NotNull
public final Person copy(int age, boolean drinking) {
return new Person(this.name, age, drinking);
}
}
48. public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", drinking=" + this.drinking + ")";
}
@NotNull
public final Person copy(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, drinking);
}
@NotNull
public final Person copy(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this.age, this.drinking);
}
@NotNull
public final Person copy(int age) {
return new Person(this.name, age, this.drinking);
}
@NotNull
public final Person copy(boolean drinking) {
return new Person(this.name, this.age, drinking);
}
@NotNull
public final Person copy(@NotNull String name, int age) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, this.drinking);
}
@NotNull
public final Person copy(@NotNull String name, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this.age, drinking);
}
@NotNull
public final Person copy(int age, boolean drinking) {
return new Person(this.name, age, drinking);
}
}
30 semicolons included
30 semicolons included
30 semicolons included
51. data class Person(
val names:List<String>,
val lastName:String,
val birthDate:LocalDate,
val email:Email,
val address:Address,
val family:List<Person>,
val drinking:Boolean = true
)
54. data class
data class
data class
simple to use immutable record
simple to use immutable record
simple to use immutable record
55. IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
First step on the road to safety (and stress free
First step on the road to safety (and stress free
First step on the road to safety (and stress free
weekends)
weekends)
weekends)
56. IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
First step on the road to safety (and stress free
First step on the road to safety (and stress free
First step on the road to safety (and stress free
weekends)
weekends)
weekends)
immutable records, objects
57. IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
First step on the road to safety (and stress free
First step on the road to safety (and stress free
First step on the road to safety (and stress free
weekends)
weekends)
weekends)
immutable records, objects
immutable data structures
58. IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
First step on the road to safety (and stress free
First step on the road to safety (and stress free
First step on the road to safety (and stress free
weekends)
weekends)
weekends)
immutable records, objects
immutable data structures
59. vavr list
vavr list
vavr list
val list1 = list(1, 2, 3)
val list2 = list1.prepend(0)
println(list1)
println(list2)
//List(1, 2, 3)
//List(0, 1, 2, 3)
63. Not all lists are born equal
Not all lists are born equal
Not all lists are born equal
io.vavr.collection.List
io.vavr.collection.List
io.vavr.collection.List >
>
>
kotlin.ImmutableList
kotlin.ImmutableList
kotlin.ImmutableList >
>
> java.util.List
java.util.List
java.util.List
64. TYPE INFERENCE
TYPE INFERENCE
TYPE INFERENCE
A small step for a man, but an average one for
A small step for a man, but an average one for
A small step for a man, but an average one for
a dwarf
a dwarf
a dwarf
67. class A(val fieldAndConstructorArf:B, onlyArg:String) {
val fieldInitializedInClass = onlyArg+"_suffix"
fun a(arg:Int):String {// :String not needed
val variable = "$arg and $fieldInitializedInClass"
val other:String = variable //:String not needed
return other
}
}
68. class A(val fieldAndConstructorArf:B, onlyArg:String) {
val fieldInitializedInClass = onlyArg+"_suffix"
fun a(arg:Int):String {// :String not needed
val variable = "$arg and $fieldInitializedInClass"
val other:String = variable //:String not needed
return other
}
}
one rule (about val)
one rule (about val)
one rule (about val) ts everywhere
ts everywhere
ts everywhere
69. Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
70. Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
any doubts?
any doubts?
any doubts?
71. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
72. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
73. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
74. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
75. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
76. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
or
or
or
77. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
or
or
or
78. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
or
or
or
79. Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
or
or
or
85. Kill statements
Kill statements
Kill statements
fun addWithStatements(a:Int, b:Int):Int {
return a + b
}
fun addAsExpression(a:Int, b:Int) = a + b
86. Kill statements
Kill statements
Kill statements
fun addWithStatements(a:Int, b:Int):Int {
return a + b
}
fun addAsExpression(a:Int, b:Int) = a + b
return
return
return is younger brother of
is younger brother of
is younger brother of GOTO
GOTO
GOTO
87. Why statements are cool? A long example.
Why statements are cool? A long example.
Why statements are cool? A long example.
sealed class Order(val sum: Int)
class Created(s: Int) : Order(s)
class Paid(s: Int) : Order(s)
class Delivered(s: Int) : Order(s)
88. sealed class Order(val sum: Int)
class Created(s: Int) : Order(s)
class Paid(s: Int) : Order(s)
class Delivered(s: Int) : Order(s)
val orders = list(
Created(120),
Paid(20),
Delivered(30),
Paid(40)
)
89. sealed class Order(val sum: Int)
class Created(s: Int) : Order(s)
class Paid(s: Int) : Order(s)
class Delivered(s: Int) : Order(s)
val orders = list(
Created(120),
Paid(20),
Delivered(30),
Paid(40)
)
fun impureSum(orders: Seq<Order>): Int {
var sum = 0
for (order in orders) {
when (order) {
is Paid -> sum = sum + order.sum
is Delivered -> sum = sum + order.sum
}
}
return sum
}
fun main() {
println(impureSum(orders)) //90
}
90. fun pureSum(orders: Seq<Order>): Int =
orders.foldLeft(0, { accumulator, order ->
when (order) {
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
})
fun main() =
println(pureSum(orders)) //90
91. fun pureSum(orders: Seq<Order>): Int =
orders.foldLeft(0) { accumulator, order ->
when (order) {
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
}
fun main() =
println(pureSum(orders)) //90
92. fun pureSum(orders: Seq<Order>): Int =
orders.foldLeft(0) { accumulator, order ->
when (order) {
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
}
fun main() =
println(pureSum(orders)) //90
fold - don't loop
fold - don't loop
fold - don't loop
93. sealed class Order(val sum: Int)
class Created(s: Int) : Order(s)
class Paid(s: Int) : Order(s)
class Delivered(s: Int) : Order(s)
class Cancelled(s:Int) : Order(s)
class Archived(s:Int) :Order(s)
val orders = list(
Created(120),
Paid(20),
Delivered(30),
Paid(40),
Cancelled(20),
Archived(10)
)
94. fun impureSum(orders: Seq<Order>): Int {
var sum = 0
for (order in orders) {
when (order) {
is Paid -> sum = sum + order.sum
is Delivered -> sum = sum + order.sum
}
}
return sum //90 - wrong
}
95. fun impureSum(orders: Seq<Order>): Int =
orders.foldLeft(0) { accumulator, order ->
when (order) {
// Error: 'when' expression must be exhaustive,
// add necessary 'is Cancelled', 'is Archived' br
// or 'else' branch instead
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
} //wont compile
96. fun impureSum(orders: Seq<Order>): Int =
orders.foldLeft(0) { accumulator, order ->
when (order) {
// Error: 'when' expression must be exhaustive,
// add necessary 'is Cancelled', 'is Archived' br
// or 'else' branch instead
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
} //wont compile
Compilation error is your friend
Compilation error is your friend
Compilation error is your friend
97. if
if
if ,,
, when
when
when,,
, try
try
try etc. are expressions in kotlin
etc. are expressions in kotlin
etc. are expressions in kotlin
fun (a:Int,b:Int) =
a + if (b<5) a else -a
98. Even more type safety
Even more type safety
Even more type safety
99. sealed class Order(internal val sum: Int) {
open fun income(): Int = sum
fun cancelled() = Cancelled(this)
}
class Created(s: Int) : Order(s) {
override fun income(): Int = 0
fun pay() = Paid(this)
}
class Paid internal constructor(order: Created) : Order(order.sum) {
fun deliver() = Delivered(this)
}
class Delivered internal constructor(order: Paid) : Order(order.sum)
fun archive() = Archived(this)
}
class Cancelled internal constructor(order: Order) : Order(order.sum)
override fun income() = 0
}
class Archived internal constructor(order: Delivered) : Order(order.s
l d li t(
100. fun perfectDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
}
106. SIDE EFFECTS
SIDE EFFECTS
SIDE EFFECTS
Functional programming is all about side
Functional programming is all about side
Functional programming is all about side
e ects
e ects
e ects
107. class Paid internal constructor(order: Created) : Order(order.sum) {
fun deliver() = Delivered(this).also {
println("delivered")
}
fun deliverFast() = Delivered(this).also {
println("delivered fast")
}
}
108. fun perfectDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
}
109. A surprise...
A surprise...
A surprise...
fun doubleDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
if (paid.income() > 20) {
paid.deliverFast()
}
}
fun main() = doubleDelivery()
//delivered
//delivered fast
110. SIDE EFFECTS
SIDE EFFECTS
SIDE EFFECTS
How not to have surprises (that often)
How not to have surprises (that often)
How not to have surprises (that often)
111. a fail
a fail
a fail
fun sayIt() = println("I said no side effects")
112. Too lazy to do side e ect
Too lazy to do side e ect
Too lazy to do side e ect
fun sayItLater() = { println("I said no side effects")}
113. Back to problem
Back to problem
Back to problem
fun crashDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
if (paid.income() > 20) {
paid.deliverFast()
}
}
114. Naleśnik == pancake
Naleśnik == pancake
Naleśnik == pancake
class Naleśnik<out A>(private val nadzienie: () -> A) {
fun <B> przepakuj(f: (A) -> B) =
Naleśnik { f(this.nadzienie()) }
fun <B> zawiń(f: (A) -> Naleśnik<B>): Naleśnik<B> =
Naleśnik { f(this.nadzienie()).nadzienie() }
fun zjedz(): A = nadzienie() //use with caution
}
115. sealed class Order(internal val sum: Int) {
open fun income(): Int = sum
fun cancelled() = Naleśnik { Cancelled(this) }
}
class Created(s: Int) : Order(s) {
override fun income(): Int = 0
fun pay() = Naleśnik { Paid(this) }
}
class Paid internal constructor(order: Created) : Order(order.sum) {
fun deliver(): Naleśnik<Delivered> = Naleśnik {
Delivered(this).also {
println("delivered")
}
}
fun deliverFast(): Naleśnik<Delivered> = Naleśnik {
Delivered(this).also {
println("delivered fast")
}
}
}
116. fun crashDelivery():Naleśnik<Delivered> = run {
val created = Created(25)
val paid = created.pay()
val delivered = paid.zawiń { it.deliver() }
paid.zawiń { if (it.income()> 20) it.deliverFast() else
}
fun main() {
crashDelivery().zjedz()
//delivered fast
}
117. Naleśnik - harder to do e ect accidentally
Naleśnik - harder to do e ect accidentally
Naleśnik - harder to do e ect accidentally
123. Transaction is a Monad
Transaction is a Monad
Transaction is a Monad
class Transaction<A>(private val action: (Connection) -> A) {
fun <B> map ( f: (A)->B) = Transaction { conn -> f(action(conn))}
fun <B> flatMap( f: (A)->Transaction<B>) =
Transaction { conn -> f(action(conn)).action(conn) }
fun runTransaction(conn:Connection): Either<Exception, A> = run {
val initialAC = conn.autoCommit
conn.autoCommit = false
try {
val res = action(conn)
conn.commit()
Either.right(res)
} catch (e: Exception) {
conn.rollback()
Either.left(e)
} finally {
conn.autoCommit = initialAC
}
}
}
127. Instead of writing:
Instead of writing:
Instead of writing:
class Hasiok {
@Resource
val jdbcConnection: Connection
@Transactional
@Secure
@Cacheable
@Retryable
fun f(p:P) {
//code
}
}
128. Write:
Write:
Write:
class Hasiok {
fun enterprisyFunction(x:Int) = Nee.pure(
secure + retryable + cache.of(x) + tx
) {jdbcConnection:Connection ->
//code using jdbcConnection
}
//declaration above means security is checked before retri
//and retrial is made before cache which happens before tr
}
129. HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
130. HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
133. If
If
If I wanted to be careful with
I wanted to be careful with
I wanted to be careful with every line I write I
every line I write I
every line I write I
would have chosen PHP
would have chosen PHP
would have chosen PHP
136. Plugin for
Plugin for
Plugin for detekt
detekt
detekt
Rule Detects Properties
with defaults
Requires
i
LoopUsage use of for, while active: true
ReturnStatement use of return statement active: true
VariableUsage use of var active: true
ReturnUnit use of function returning Unit, Nothing,
Void
active: true
checkFunctionType:
true
:ballot_box_with_check:
ClassDe nition use of object-oriented class active: false
AbstractClassDe nition use of object-oriented abstract class active: false
ThrowExpression use of throw active: true
MutableCollections use of mutable collections active: true :ballot_box_with_check:
BranchStatement use of if or when as statement :white_check_mark:
MissingElse use of if statement without else
type resolution
139. example of pure todo list with arrow-fx and
example of pure todo list with arrow-fx and
example of pure todo list with arrow-fx and
ktor
ktor
ktor
springy e ects for kotlin
springy e ects for kotlin
springy e ects for kotlin
example ktor project with Nee ("todo list like")
example ktor project with Nee ("todo list like")
example ktor project with Nee ("todo list like")
https://github.com/nee ect/kure-potlin
https://github.com/nee ect/kure-potlin
https://github.com/nee ect/kure-potlin
https://github.com/jarekratajski/just_another_to
https://github.com/jarekratajski/just_another_to
https://github.com/jarekratajski/just_another_to
https://github.com/nee ect/nee
https://github.com/nee ect/nee
https://github.com/nee ect/nee
https://github.com/nee ect/kotlin-stones
https://github.com/nee ect/kotlin-stones
https://github.com/nee ect/kotlin-stones
https://demo.nee ect.dev
https://demo.nee ect.dev
https://demo.nee ect.dev
140. SUMMARY
SUMMARY
SUMMARY
FP is not a silver bullet, but it can help ->
FP is not a silver bullet, but it can help ->
FP is not a silver bullet, but it can help ->
composability.
composability.
composability.
The road is long and has multiple
The road is long and has multiple
The road is long and has multiple milestones
milestones
milestones
Each milestone is a
Each milestone is a
Each milestone is a potential profit
potential profit
potential profit
Kotlin is not Scala - but can be quite pure
Kotlin is not Scala - but can be quite pure
Kotlin is not Scala - but can be quite pure
Runtime magic vs Compiler magic
Runtime magic vs Compiler magic
Runtime magic vs Compiler magic