SlideShare a Scribd company logo
PURE KOTLIN
PURE KOTLIN
PURE KOTLIN
Kod/linki:
Kod/linki:
Kod/linki:
AGENDA
AGENDA
AGENDA
AGENDA
AGENDA
AGENDA
Propaganda
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
Frameworks
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
Frameworks
Rules
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
Frameworks
Rules
Propaganda
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
Frameworks
Rules
Propaganda
Questions, answers, examples,
demos, disasters
PART 1
PART 1
PART 1
FP
FP
FP
PART 1
PART 1
PART 1
FP
FP
FP
FUNCTIONAL PROPAGANDA
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
Pure kotlin
FP PROMISES
FP PROMISES
less errors
FP PROMISES
less errors
less code
FP PROMISES
less errors
less code
less tests
FP PROMISES
less errors
less code
less tests
LESS != Nil
LESS != Nil
LESS != Nil
Two hours after deployment
Two hours after deployment
Two hours after deployment
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
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
What is functional programming?
What is functional programming?
What is functional programming?
Programming with functions:
Programming with functions:
Programming with functions:
deterministic
total
pure
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 ;-)
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
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 */
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]
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")
}
Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
COMPOSABILITY
COMPOSABILITY
COMPOSABILITY
PART 2
PART 2
PART 2
KOTLIN PROPAGANDA
KOTLIN PROPAGANDA
KOTLIN PROPAGANDA
Kotlin killer feature?
Kotlin killer feature?
Kotlin killer feature?
No semicolon
No semicolon
No semicolon
Data class
Data class
Data class
kotlin
kotlin
kotlin
data class Person(
val name:String,
val age:Int,
val drinking:Boolean = true
)
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;
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
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;
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
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;
}
}
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() {
Back to kotlin
Back to kotlin
Back to kotlin
fun main() = run {
val p = Person("irek", 27, true)
//
}
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)
}
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)
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;
}
}
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);
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
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);
}
}
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
data class Person(val name:String, val age:Int, val drinking:Boolean = true)
data class Person(
val name:String,
val age:Int,
val drinking:Boolean = true
)
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
)
Unfortunately,
Unfortunately,
Unfortunately, copy
copy
copy is not yet included (as of
is not yet included (as of
is not yet included (as of
java 16)
java 16)
java 16) in
in
in java records
java records
java records
data class
data class
data class
data class
data class
data class
simple to use immutable record
simple to use immutable record
simple to use immutable record
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)
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
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
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
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)
kotlin immutable (default list)
kotlin immutable (default list)
kotlin immutable (default list)
val list1 = listOf(1, 2, 3)
val list2 = listOf(0)+ list1 // not efficient
println(list1)
println(list2)
//[1, 2, 3]
//[0, 1, 2, 3]
val list1 = listOf(1, 2, 3)
val list2 = listOf(0)+ list1
(list1 as MutableList)[1] = -1
println(list1)
println(list2)
//[1, -1, 3]
//[0, 1, 2, 3]
java.util.ArrayList
java.util.ArrayList
java.util.ArrayList a total disaster
a total disaster
a total disaster
val list1 = ArrayList(listOf(1,2,3))
for (el in list1 ) {
list1.add(list1.size)
}
println(list1)
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
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
Pure kotlin
fun main() {
val x = "Hello Kielce JUG"
}
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
}
}
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
Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
any doubts?
any doubts?
any doubts?
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
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
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
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
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
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
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
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
val x:HashMap<Security.Id,List<Either<Group,User>>> = ...
typealias SecurityRegistry = HashMap<Security.Id,List<Either<G
val x:SecurityRegistry = ...
NEXT STEP
NEXT STEP
NEXT STEP
Expressions
Expressions
Expressions
Esspressions
Esspressions
Esspressions
ii
i
Kill statements
Kill statements
Kill statements
fun addWithStatements(a:Int, b:Int):Int {
return a + b
}
fun addAsExpression(a:Int, b:Int) = a + b
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
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)
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)
)
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
}
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
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
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
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)
)
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
}
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
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
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
Even more type safety
Even more type safety
Even more type safety
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(
fun perfectDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
}
TOTALITARISM
TOTALITARISM
TOTALITARISM
Sounds like a wrong step. Let's see.
Sounds like a wrong step. Let's see.
Sounds like a wrong step. Let's see.
Say no to
Say no to
Say no to expected exceptions
expected exceptions
expected exceptions
fun parse(s:String) : Int = s.toInt()
fun String.asInt(): Either<ParseError, Int> =
if (this != null && this.matches(Regex("-?[0-9]+"))) {
this.toInt().right()
} else {
ParseError.WrongCharacters(this).left()
}

val z = "124".asInt()
Checked exceptions | 4xx =>
Checked exceptions | 4xx =>
Checked exceptions | 4xx => Either
Either
Either
Runtime exceptions | 5xx => Runtime
Runtime exceptions | 5xx => Runtime
Runtime exceptions | 5xx => Runtime
Exceptions
Exceptions
Exceptions
SIDE EFFECTS
SIDE EFFECTS
SIDE EFFECTS
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
class Paid internal constructor(order: Created) : Order(order.sum) {
fun deliver() = Delivered(this).also {
println("delivered")
}
fun deliverFast() = Delivered(this).also {
println("delivered fast")
}
}
fun perfectDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
}
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
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)
a fail
a fail
a fail
fun sayIt() = println("I said no side effects")
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")}
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()
}
}
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
}
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")
}
}
}
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
}
Naleśnik - harder to do e ect accidentally
Naleśnik - harder to do e ect accidentally
Naleśnik - harder to do e ect accidentally
Naleśnik > Burrito
Naleśnik > Burrito
Naleśnik > Burrito
Naleśnik
Naleśnik
Naleśnik == IO (Monad)
== IO (Monad)
== IO (Monad)
IO <A>
IO <A>
IO <A> ~=
~=
~= Mono<A>
Mono<A>
Mono<A>
in
in
in arrow-fx
arrow-fx
arrow-fx
IO<A>
IO<A>
IO<A> ==
==
== suspend () -> A
suspend () -> A
suspend () -> A
FRAMEWORKS - ENTERPRISY
FRAMEWORKS - ENTERPRISY
FRAMEWORKS - ENTERPRISY
CODE
CODE
CODE
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
}
}
}
GENERIC EFFECT
IO<R,E,A>
IO<R,E,A>
IO<R,E,A>
R - environment (dependencies)
E - error (not only exception)
A - result (business)
Scala ZIO
Scala ZIO
Scala ZIO
NEE
mutilated
mutilated
mutilated ZIO <R,E,A>
ZIO <R,E,A>
ZIO <R,E,A> + spring like aspects
+ spring like aspects
+ spring like aspects
description
description
description
Instead of writing:
Instead of writing:
Instead of writing:
class Hasiok {
@Resource
val jdbcConnection: Connection
@Transactional
@Secure
@Cacheable
@Retryable
fun f(p:P) {
//code
}
}
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
}
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
What about discipline?
What about discipline?
What about discipline?
Pure kotlin
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
KURE-POTLIN
KURE-POTLIN
KURE-POTLIN
https://github.com/nee ect/kure-potlin
https://github.com/nee ect/kure-potlin
https://github.com/nee ect/kure-potlin
Plugin for
Plugin for
Plugin for detekt
detekt
detekt
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
PROJECT LINKS
PROJECT LINKS
PROJECT LINKS
Pure kotlin
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
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

More Related Content

PDF
Transaction is a monad
PPTX
Kotlin collections
PDF
Sneaking inside Kotlin features
PPTX
The Groovy Puzzlers – The Complete 01 and 02 Seasons
PDF
TDC2016SP - Código funcional em Java: superando o hype
ODP
Scala 2 + 2 > 4
PPTX
Benefits of Kotlin
PDF
Java 8 - Nuts and Bold - SFEIR Benelux
Transaction is a monad
Kotlin collections
Sneaking inside Kotlin features
The Groovy Puzzlers – The Complete 01 and 02 Seasons
TDC2016SP - Código funcional em Java: superando o hype
Scala 2 + 2 > 4
Benefits of Kotlin
Java 8 - Nuts and Bold - SFEIR Benelux

What's hot (20)

PPTX
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
PDF
Google guava
PDF
Kotlin Generation
PPTX
Programming Java - Lection 04 - Generics and Lambdas - Lavrentyev Fedor
PDF
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
PDF
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
PDF
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
KEY
Google Guava
PDF
Google Guava for cleaner code
PDF
Nik Graf - Get started with Reason and ReasonReact
KEY
Why Learn Python?
PPT
Developing iOS apps with Swift
PDF
Google guava - almost everything you need to know
PPTX
Kotlin standard
PDF
The Magic Of Elixir
ODP
Scala introduction
PDF
6. Generics. Collections. Streams
PDF
Java 8 Streams & Collectors : the Leuven edition
KEY
Into Clojure
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Google guava
Kotlin Generation
Programming Java - Lection 04 - Generics and Lambdas - Lavrentyev Fedor
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Google Guava
Google Guava for cleaner code
Nik Graf - Get started with Reason and ReasonReact
Why Learn Python?
Developing iOS apps with Swift
Google guava - almost everything you need to know
Kotlin standard
The Magic Of Elixir
Scala introduction
6. Generics. Collections. Streams
Java 8 Streams & Collectors : the Leuven edition
Into Clojure
Ad

Similar to Pure kotlin (20)

PDF
Pure Kotlin Devoxx PL 2021
PPTX
PDF
Effective Java and Kotlin
PDF
PDF
Feel of Kotlin (Berlin JUG 16 Apr 2015)
PPTX
Kotlin : Happy Development
PPTX
Introduction to Kotlin
PDF
From java to kotlin beyond alt+shift+cmd+k
PDF
Kotlin for Android Developers
PDF
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
PDF
Having Fun with Kotlin Android - DILo Surabaya
PDF
Kotlin: forse è la volta buona (Trento)
PDF
Kotlin Bytecode Generation and Runtime Performance
PDF
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
PPTX
K is for Kotlin
PDF
2014-11-01 01 Денис Нелюбин. О сортах кофе
PDF
No excuses, switch to kotlin
PDF
Kotlin: maybe it's the right time
PDF
かとうの Kotlin 講座 こってり版
PDF
Intro to Kotlin
Pure Kotlin Devoxx PL 2021
Effective Java and Kotlin
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Kotlin : Happy Development
Introduction to Kotlin
From java to kotlin beyond alt+shift+cmd+k
Kotlin for Android Developers
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Having Fun with Kotlin Android - DILo Surabaya
Kotlin: forse è la volta buona (Trento)
Kotlin Bytecode Generation and Runtime Performance
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
K is for Kotlin
2014-11-01 01 Денис Нелюбин. О сортах кофе
No excuses, switch to kotlin
Kotlin: maybe it's the right time
かとうの Kotlin 講座 こってり版
Intro to Kotlin
Ad

More from Jarek Ratajski (15)

PDF
respect-estimates.pdf
PDF
Lambda hardcore
PDF
Scala to assembly
PDF
Spring, CDI, Jakarta EE good parts
PDF
Eta lang Beauty And The Beast
PDF
Another programming language - jeszcze jeden język
PDF
Beauty and the beast - Haskell on JVM
ODP
Fighting null with memes
ODP
Geecon walking in CODE
PDF
Scalaworld lambda core hardcore
PDF
Lambda core
ODP
[4 dev] lagom
ODP
Jdd 2016 DROP DATABASE
ODP
DROPDB Galactic story
respect-estimates.pdf
Lambda hardcore
Scala to assembly
Spring, CDI, Jakarta EE good parts
Eta lang Beauty And The Beast
Another programming language - jeszcze jeden język
Beauty and the beast - Haskell on JVM
Fighting null with memes
Geecon walking in CODE
Scalaworld lambda core hardcore
Lambda core
[4 dev] lagom
Jdd 2016 DROP DATABASE
DROPDB Galactic story

Recently uploaded (20)

PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Digital Systems & Binary Numbers (comprehensive )
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
assetexplorer- product-overview - presentation
PPTX
Transform Your Business with a Software ERP System
PDF
PTS Company Brochure 2025 (1).pdf.......
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PPTX
history of c programming in notes for students .pptx
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PDF
Understanding Forklifts - TECH EHS Solution
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
System and Network Administration Chapter 2
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Design an Analysis of Algorithms I-SECS-1021-03
Digital Systems & Binary Numbers (comprehensive )
Operating system designcfffgfgggggggvggggggggg
Which alternative to Crystal Reports is best for small or large businesses.pdf
wealthsignaloriginal-com-DS-text-... (1).pdf
assetexplorer- product-overview - presentation
Transform Your Business with a Software ERP System
PTS Company Brochure 2025 (1).pdf.......
CHAPTER 2 - PM Management and IT Context
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Wondershare Filmora 15 Crack With Activation Key [2025
Navsoft: AI-Powered Business Solutions & Custom Software Development
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
history of c programming in notes for students .pptx
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
Understanding Forklifts - TECH EHS Solution
How to Choose the Right IT Partner for Your Business in Malaysia
System and Network Administration Chapter 2
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf

Pure kotlin

  • 1. PURE KOTLIN PURE KOTLIN PURE KOTLIN Kod/linki: Kod/linki: Kod/linki:
  • 8. AGENDA AGENDA AGENDA Propaganda Propaganda The road to purity Frameworks Rules Propaganda
  • 9. AGENDA AGENDA AGENDA Propaganda Propaganda The road to purity Frameworks Rules Propaganda Questions, answers, examples, demos, disasters
  • 10. PART 1 PART 1 PART 1 FP FP FP
  • 11. PART 1 PART 1 PART 1 FP FP FP FUNCTIONAL PROPAGANDA
  • 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
  • 17. FP PROMISES less errors less code less tests
  • 18. FP PROMISES less errors less code less tests LESS != Nil LESS != Nil LESS != Nil
  • 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
  • 31. Kotlin killer feature? Kotlin killer feature? Kotlin killer feature?
  • 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() {
  • 40. Back to kotlin Back to kotlin Back to kotlin
  • 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
  • 49. data class Person(val name:String, val age:Int, val drinking:Boolean = true)
  • 50. data class Person( val name:String, val age:Int, val drinking:Boolean = true )
  • 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 )
  • 52. Unfortunately, Unfortunately, Unfortunately, copy copy copy is not yet included (as of is not yet included (as of is not yet included (as of java 16) java 16) java 16) in in in java records java records java records
  • 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)
  • 60. kotlin immutable (default list) kotlin immutable (default list) kotlin immutable (default list) val list1 = listOf(1, 2, 3) val list2 = listOf(0)+ list1 // not efficient println(list1) println(list2) //[1, 2, 3] //[0, 1, 2, 3]
  • 61. val list1 = listOf(1, 2, 3) val list2 = listOf(0)+ list1 (list1 as MutableList)[1] = -1 println(list1) println(list2) //[1, -1, 3] //[0, 1, 2, 3]
  • 62. java.util.ArrayList java.util.ArrayList java.util.ArrayList a total disaster a total disaster a total disaster val list1 = ArrayList(listOf(1,2,3)) for (el in list1 ) { list1.add(list1.size) } println(list1)
  • 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
  • 66. fun main() { val x = "Hello Kielce JUG" }
  • 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
  • 81. typealias SecurityRegistry = HashMap<Security.Id,List<Either<G val x:SecurityRegistry = ...
  • 82. NEXT STEP NEXT STEP NEXT STEP Expressions Expressions Expressions
  • 84. ii i
  • 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() }
  • 101. TOTALITARISM TOTALITARISM TOTALITARISM Sounds like a wrong step. Let's see. Sounds like a wrong step. Let's see. Sounds like a wrong step. Let's see.
  • 102. Say no to Say no to Say no to expected exceptions expected exceptions expected exceptions fun parse(s:String) : Int = s.toInt()
  • 103. fun String.asInt(): Either<ParseError, Int> = if (this != null && this.matches(Regex("-?[0-9]+"))) { this.toInt().right() } else { ParseError.WrongCharacters(this).left() } val z = "124".asInt()
  • 104. Checked exceptions | 4xx => Checked exceptions | 4xx => Checked exceptions | 4xx => Either Either Either Runtime exceptions | 5xx => Runtime Runtime exceptions | 5xx => Runtime Runtime exceptions | 5xx => Runtime Exceptions Exceptions Exceptions
  • 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
  • 118. Naleśnik > Burrito Naleśnik > Burrito Naleśnik > Burrito
  • 119. Naleśnik Naleśnik Naleśnik == IO (Monad) == IO (Monad) == IO (Monad)
  • 120. IO <A> IO <A> IO <A> ~= ~= ~= Mono<A> Mono<A> Mono<A>
  • 121. in in in arrow-fx arrow-fx arrow-fx IO<A> IO<A> IO<A> == == == suspend () -> A suspend () -> A suspend () -> A
  • 122. FRAMEWORKS - ENTERPRISY FRAMEWORKS - ENTERPRISY FRAMEWORKS - ENTERPRISY CODE CODE CODE
  • 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 } } }
  • 124. GENERIC EFFECT IO<R,E,A> IO<R,E,A> IO<R,E,A> R - environment (dependencies) E - error (not only exception) A - result (business)
  • 126. NEE mutilated mutilated mutilated ZIO <R,E,A> ZIO <R,E,A> ZIO <R,E,A> + spring like aspects + spring like aspects + spring like aspects description description description
  • 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?
  • 131. What about discipline? What about discipline? What about discipline?
  • 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
  • 135. Plugin for Plugin for Plugin for detekt detekt detekt
  • 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