SlideShare a Scribd company logo
DEVOXX PL 2021
DEVOXX PL 2021
DEVOXX PL 2021
PURE KOTLIN
PURE KOTLIN
PURE KOTLIN
links
links
links
Jarek Ratajski
Jarek Ratajski
Jarek Ratajski
working for
working for
working for Digital Asset
Digital Asset
Digital Asset
This talk does not represent company views, it
This talk does not represent company views, it
This talk does not represent company views, it
is based on personal experience
is based on personal experience
is based on personal experience and opinions
and opinions
and opinions
AGENDA
AGENDA
AGENDA
AGENDA
AGENDA
AGENDA
Propaganda
AGENDA
AGENDA
AGENDA
Propaganda
The road to purity
AGENDA
AGENDA
AGENDA
Propaganda
The road to purity
How to stay pure
AGENDA
AGENDA
AGENDA
Propaganda
The road to purity
How to stay pure
Links, frameworks, examples,
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
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
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 definition
Ok, I have no idea. Just copied this definition
Ok, I have no idea. Just copied this definition
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
fun
fun hello() = "Hello Devoxx Poland"

fun
fun
fun fact(n:Int) = if
if
if (n<=1) 1 else
else
else n*fact(n-1)

fun
fun
fun radom() = Math.random()*0.7
TOTAL:
Yields result/finishes for all possible arguments
Yields result/finishes for all possible arguments
Yields result/finishes for all possible arguments
fun
fun
fun negate(a:Int):Int = -a

fun
fun
fun radomize(v:String) = "Radom znowu $v"

fun
fun
fun parseInt(t:String):Int = /* whatever */
PURE:
Leaves no traces.
Leaves no traces.
Leaves no traces. The only (practical) way to
The only (practical) way to
The only (practical) way to
detect if the function was called is by reading a
detect if the function was called is by reading a
detect if the function was called is by reading a
result.
result.
result.
fun
fun
fun add(a:Int, b:Int) = a+b 

[CODE A]

val
val
val x = add(6,3) [OR] val
val
val x = 9

[CODE B]
fun
fun
fun add(a:Int, b:Int) = a*b //happy debugging

fun
fun
fun add2(a:Int, b:Int) = run {

Thread.sleep(a*1000)

Thread.sleep(b*1000)

return
return
return a+b

}

fun
fun
fun add3(a:Int, b:Int) = (a+b).also {

log("was adding something...")
}
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
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?
Keyboard used by java developer
Keyboard used by java developer
Keyboard used by java developer
Kotlin
Kotlin
Kotlin == No more semicolons
== No more semicolons
== No more semicolons
Data class
Data class
Data class
kotlin
kotlin
kotlin
data
data
data class
class
class Person(

val
val
val name:String, 

val
val
val age:Int, 

val
val
val drinking:Boolean = true

)
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

}
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

}
val drinking:Boolean = true
val drinking:Boolean = true
val drinking:Boolean = true
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String
String
String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String
String
String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String
String
String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

public
public
public Person(@NotNull String
String
String name, int
int
int age) {

this
this
this(name, age, true);
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String
String
String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String
String
String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String
String
String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

public
public
public Person(@NotNull String
String
String name, int
int
int age) {

this
this
this(name, age, true);

equals and hashCode
equals and hashCode
equals and hashCode
public
public
public int
int
int hashCode() {

String var10000 = this
this
this.name;

int
int
int var1 = ((var10000 != null
null
null ? var10000.hashCode() : 0) * 31 + this
this
this.
return
return
return var1 + (drinking ? 1 : 0);

}

public
public
public boolean
boolean
boolean equals(@Nullable Object var1) {

if
if
if (this
this
this != var1) {

if
if
if (var1 instanceof
instanceof
instanceof Person) {

Person var2 = (Person) var1;

if
if
if (Intrinsics.areEqual(this
this
this.name, var2.name) 

&& this
this
this.age == var2.age 

&& this
this
this.drinking == var2.drinking) {

return
return
return true
true
true;

}
}

return
return
return false
false
false;

} else
else
else {

return
return
return true
true
true;

}

}
public
public
public int hashCode() {

String var10000 = this
this
this.name;

int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this
this
this.
return
return
return var1 + (drinking ? 1 : 0);

}

public
public
public boolean equals(@Nullable Object var1) {

if
if
if (this
this
this != var1) {

if
if
if (var1 instanceof Person) {

Person var2 = (Person) var1;

if
if
if (Intrinsics.areEqual(this
this
this.name, var2.name) 

&& this
this
this.age == var2.age 

&& this
this
this.drinking == var2.drinking) {

return
return
return true;

}
}

return
return
return false;

} else
else
else {

return
return
return true;

}

}

@NotNull

public
public
public String toString() {

return
return
return "Person(name=" + this
this
this.name + ", age=" + this
this
this.age + ", drinking
}
Back to kotlin
Back to kotlin
Back to kotlin
fun
fun
fun main() = run {

val
val
val p = Person("irek", 27, true)

//

}
fun
fun
fun main() = run {

val
val
val p = Person("irek", 27, true)

val
val
val p1 = p.copy(name = "Irek")

}
fun
fun
fun main() = run {

val
val
val p = Person("irek", 27, true)

val
val
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
fun
fun main() = run {

val
val
val p = Person("irek", 27, true)

val
val
val p1 = p.copy(name = "Irek")

val
val
val p2 = p1.copy(age = 28)

}
fun
fun
fun main() = run {

val
val
val p = Person("irek", 27, true)

val
val
val p1 = p.copy(name = "Irek")

val
val
val p2 = p1.copy(age = 28)

val
val
val p3 = p2.copy(drinking = false)

}
fun
fun
fun main() = run {

val
val
val p = Person("irek", 27, true)

val
val
val p1 = p.copy(name = "Irek")

val
val
val p2 = p1.copy(age = 28)

val
val
val p3 = p2.copy(drinking = false)

val
val
val p4 = p3.copy(age = 29, drinking = true)

}

//Person(name=Zdzich, age=30, drinking=false)
fun
fun
fun main() = run {

val
val
val p = Person("irek", 27, true)

val
val
val p1 = p.copy(name = "Irek")

val
val
val p2 = p1.copy(age = 28)

val
val
val p3 = p2.copy(drinking = false)

val
val
val p4 = p3.copy(age = 29, drinking = true)

val
val
val p5 = p4.copy(name = "Zdzich", age = p4.age+1, drinking = false)

println(p3) //Person(name=Irek, age=28, drinking=false)

println(p5) //Person(name=Zdzich, age=30, drinking=false)

}
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

public
public
public Person(@NotNull String name, int
int
int age) {

this
this
this(name, age, true
true
true);

}

public
public
public int
int
int hashCode() {

String var10000 = this
this
this.name;

int
int
int var1 = ((var10000 != null
null
null ? var10000.hashCode() : 0) * 31 + this
this
this.age) * 31;

return
return
return var1 + (drinking ? 1 : 0);

}

public
public
public boolean
boolean
boolean equals(@Nullable Object var1) {

if
if
if (this
this
this != var1) {

if
if
if (var1 instanceof
instanceof
instanceof Person) {

Person var2 = (Person) var1;

if
if
if (Intrinsics.areEqual(this
this
this.name, var2.name) && this
this
this.age == var2.age && this
this
this.drinking == var2.drinking) {

return
return
return true
true
true;

}

}

return
return
return false
false
false;

} else
else
else {

return
return
return true
true
true;

}

}

@NotNull

public
public
public String toString() {

return
return
return "Person(name=" + this
this
this.name + ", age=" + this
this
this.age + ", drinking=" + this
this
this.drinking + ")";

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

public
public
public Person(@NotNull String name, int
int
int age) {

this
this
this(name, age, true
true
true);

}

public
public
public int
int
int hashCode() {

String var10000 = this
this
this.name;

int
int
int var1 = ((var10000 != null
null
null ? var10000.hashCode() : 0) * 31 + this
this
this.age) * 31;

return
return
return var1 + (drinking ? 1 : 0);

}

public
public
public boolean
boolean
boolean equals(@Nullable Object var1) {

if
if
if (this
this
this != var1) {

if
if
if (var1 instanceof
instanceof
instanceof Person) {

Person var2 = (Person) var1;

if
if
if (Intrinsics.areEqual(this
this
this.name, var2.name) && this
this
this.age == var2.age && this
this
this.drinking == var2.drinking) {

return
return
return true
true
true;

}

}

return
return
return false
false
false;

} else
else
else {

return
return
return true
true
true;

}

}

@NotNull

public
public
public String toString() {

return
return
return "Person(name=" + this
this
this.name + ", age=" + this
this
this.age + ", drinking=" + this
this
this.drinking + ")";

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, age, drinking);

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, this
this
this.age, this
this
this.drinking);

}

@NotNull

public
public
public final
final
final Person copy(int
int
int age) {

return
return
return new
new
new Person(this
this
this.name, age, this
this
this.drinking);

}
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

public
public
public Person(@NotNull String name, int
int
int age) {

this
this
this(name, age, true
true
true);

}

public
public
public int
int
int hashCode() {

String var10000 = this
this
this.name;

int
int
int var1 = ((var10000 != null
null
null ? var10000.hashCode() : 0) * 31 + this
this
this.age) * 31;

return
return
return var1 + (drinking ? 1 : 0);

}

public
public
public boolean
boolean
boolean equals(@Nullable Object var1) {

if
if
if (this
this
this != var1) {

if
if
if (var1 instanceof
instanceof
instanceof Person) {

Person var2 = (Person) var1;

if
if
if (Intrinsics.areEqual(this
this
this.name, var2.name) && this
this
this.age == var2.age && this
this
this.drinking == var2.drinking) {

return
return
return true
true
true;

}

}

return
return
return false
false
false;

} else
else
else {

return
return
return true
true
true;

}

}

@NotNull

public
public
public String toString() {

return
return
return "Person(name=" + this
this
this.name + ", age=" + this
this
this.age + ", drinking=" + this
this
this.drinking + ")";

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, age, drinking);

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, this
this
this.age, this
this
this.drinking);

}

@NotNull

public
public
public final
final
final Person copy(int
int
int age) {

return
return
return new
new
new Person(this
this
this.name, age, this
this
this.drinking);

}

almost
almost
almost
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

public
public
public Person(@NotNull String name, int
int
int age) {

this
this
this(name, age, true
true
true);

}

public
public
public int
int
int hashCode() {

String var10000 = this
this
this.name;

int
int
int var1 = ((var10000 != null
null
null ? var10000.hashCode() : 0) * 31 + this
this
this.age) * 31;

return
return
return var1 + (drinking ? 1 : 0);

}

public
public
public boolean
boolean
boolean equals(@Nullable Object var1) {

if
if
if (this
this
this != var1) {

if
if
if (var1 instanceof
instanceof
instanceof Person) {

Person var2 = (Person) var1;

if
if
if (Intrinsics.areEqual(this
this
this.name, var2.name) && this
this
this.age == var2.age && this
this
this.drinking == var2.drinking) {

return
return
return true
true
true;

}

}

return
return
return false
false
false;

} else
else
else {

return
return
return true
true
true;

}

}

@NotNull

public
public
public String toString() {

return
return
return "Person(name=" + this
this
this.name + ", age=" + this
this
this.age + ", drinking=" + this
this
this.drinking + ")";

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, age, drinking);

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, this
this
this.age, this
this
this.drinking);

}

@NotNull

public
public
public final
final
final Person copy(int
int
int age) {

return
return
return new
new
new Person(this
this
this.name, age, this
this
this.drinking);

}

@NotNull

public
public
public final
final
final Person copy(boolean
boolean
boolean drinking) {

return
return
return new
new
new Person(this
this
this.name, this
this
this.age, drinking);

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, int
int
int age) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, age, this
this
this.drinking);

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, this
this
this.age, drinking);

}

@NotNull
public
public
public final
final
final class
class
class Person {

@NotNull

private
private
private final
final
final String name;

private
private
private final
final
final int
int
int age;

private
private
private final
final
final boolean
boolean
boolean drinking;

@NotNull

public
public
public final
final
final String getName() {

return
return
return this
this
this.name;

}

public
public
public final
final
final int
int
int getAge() {

return
return
return this
this
this.age;

}

public
public
public final
final
final boolean
boolean
boolean getDrinking() {

return
return
return this
this
this.drinking;

}

public
public
public Person(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

this
this
this.name = name;

this
this
this.age = age;

this
this
this.drinking = drinking;

}

public
public
public Person(@NotNull String name, int
int
int age) {

this
this
this(name, age, true
true
true);

}

public
public
public int
int
int hashCode() {

String var10000 = this
this
this.name;

int
int
int var1 = ((var10000 != null
null
null ? var10000.hashCode() : 0) * 31 + this
this
this.age) * 31;

return
return
return var1 + (drinking ? 1 : 0);

}

public
public
public boolean
boolean
boolean equals(@Nullable Object var1) {

if
if
if (this
this
this != var1) {

if
if
if (var1 instanceof
instanceof
instanceof Person) {

Person var2 = (Person) var1;

if
if
if (Intrinsics.areEqual(this
this
this.name, var2.name) && this
this
this.age == var2.age && this
this
this.drinking == var2.drinking) {

return
return
return true
true
true;

}

}

return
return
return false
false
false;

} else
else
else {

return
return
return true
true
true;

}

}

@NotNull

public
public
public String toString() {

return
return
return "Person(name=" + this
this
this.name + ", age=" + this
this
this.age + ", drinking=" + this
this
this.drinking + ")";

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, int
int
int age, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, age, drinking);

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, this
this
this.age, this
this
this.drinking);

}

@NotNull

public
public
public final
final
final Person copy(int
int
int age) {

return
return
return new
new
new Person(this
this
this.name, age, this
this
this.drinking);

}

@NotNull

public
public
public final
final
final Person copy(boolean
boolean
boolean drinking) {

return
return
return new
new
new Person(this
this
this.name, this
this
this.age, drinking);

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, int
int
int age) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, age, this
this
this.drinking);

}

@NotNull

public
public
public final
final
final Person copy(@NotNull String name, boolean
boolean
boolean drinking) {

Intrinsics.checkNotNullParameter(name, "name");

return
return
return new
new
new Person(name, this
this
this.age, drinking);

}

@NotNull
30 semicolons included
30 semicolons included
30 semicolons included
data
data
data class
class
class Person(val
val
val name:String, val
val
val age:Int, val
val
val drinking:Boolean = true)
data
data
data class
class
class Person(

val
val
val name:String, 

val
val
val age:Int, 

val
val
val drinking:Boolean = true

)
data
data
data class
class
class Person(

val
val
val names:List<String>,

val
val
val lastName:String,

val
val
val birthDate:LocalDate,

val
val
val email:Email,

val
val
val address:Address,

val
val
val family:List<Person>,

val
val
val drinking:Boolean = true

)
In java there are
In java there are
In java there are records
records
records but unfortunately as
but unfortunately as
but unfortunately as
for
for
for java 16
java 16
java 16 there is nothing like
there is nothing like
there is nothing like .copy(...)
.copy(...)
.copy(...)
yet.
yet.
yet.
data class
data class
data class
data class
data class
data class
Simple immutable record
Simple immutable record
Simple immutable record
PURE CODE RULES
PURE CODE RULES
PURE CODE RULES
The most important rule:
The most important rule:
The most important rule:
The most important rule:
The most important rule:
The most important rule:
Don't be like COVID-19
Don't be like COVID-19
Don't be like COVID-19
The most important rule:
The most important rule:
The most important rule:
Don't be like COVID-19
Don't be like COVID-19
Don't be like COVID-19
The most important rule:
The most important rule:
The most important rule:
Don't be like COVID-19
Don't be like COVID-19
Don't be like COVID-19
Do not mutate
Do not mutate
Do not mutate
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
immutable records, objects
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
immutable records, objects
immutable data structures
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
immutable records, objects
immutable data structures
vavr list
vavr list
vavr list
val
val
val list1 = list(1, 2, 3)

val
val
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
val
val list1 = listOf(1, 2, 3)

val
val
val list2 = listOf(0) + list1 // not efficient

println(list1)

println(list2)

//[1, 2, 3]

//[0, 1, 2, 3]
val
val
val list1 = listOf(1, 2, 3)

val
val
val list2 = listOf(0) + list1

(list1 as
as
as MutableList)[1] = -1 

println(list1)

println(list2)

//[1, -1, 3]

//[0, 1, 2, 3]
java.util.ArrayList
java.util.ArrayList
java.util.ArrayList mutable by design
mutable by design
mutable by design
val
val
val list1 = ArrayList(listOf(1,2,3))

for
for
for (el in
in
in list1 ) {

list1.add(list1.size)

}

println(list1)
Not all Lists are created equal
Not all Lists are created equal
Not all Lists are created 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
(for
(for
(for typical
typical
typical business
business
business code)
code)
code)
TYPE INFERENCE
TYPE INFERENCE
TYPE INFERENCE
HAVING A TYPE BUT NOT TYPING THE
TYPE
fun
fun
fun main() {

val
val
val x = "Devoxx Poland"

}
val variableName : OptionalType = ...
val variableName : OptionalType = ...
val variableName : OptionalType = ...
class
class
class A(val
val
val fieldAndConstructorArf:B, onlyArg:String) {

val
val
val fieldInitializedInClass = onlyArg+"_suffix"

fun
fun
fun a(arg:Int):String {// :String not needed

val
val
val variable = "$arg and $fieldInitializedInClass"

val
val
val other:String = variable //:String not needed

return
return
return other 

}

}
val variableName : OptionalType = ...
val variableName : OptionalType = ...
val variableName : OptionalType = ...
class
class
class A(val
val
val fieldAndConstructorArf:B, onlyArg:String) {

val
val
val fieldInitializedInClass = onlyArg+"_suffix"

fun
fun
fun a(arg:Int):String {// :String not needed

val
val
val variable = "$arg and $fieldInitializedInClass"

val
val
val other:String = variable //:String not needed

return
return
return other 

}

}
one simple syntax rule - fits everywhere
one simple syntax rule - fits everywhere
one simple syntax rule - fits 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
doubts?
doubts?
doubts?
Which password policy is better (safer)?
Which password policy is better (safer)?
Which password policy is better (safer)?
Which password policy is better (safer)?
Which password policy is better (safer)?
Which password policy is better (safer)?
at least 12 characters
Which password policy is better (safer)?
Which password policy is better (safer)?
Which password policy is better (safer)?
at least 12 characters
must include upper, lower case, digit and
special character
Which password policy is better (safer)?
Which password policy is better (safer)?
Which password policy is better (safer)?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
Which password policy is better (safer)?
Which password policy is better (safer)?
Which password policy is better (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 better (safer)?
Which password policy is better (safer)?
Which password policy is better (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 better (safer)?
Which password policy is better (safer)?
Which password policy is better (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 better (safer)?
Which password policy is better (safer)?
Which password policy is better (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 better (safer)?
Which password policy is better (safer)?
Which password policy is better (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
val
val x:HashMap<Security.Id,List<Either<Group,User>>> = ...
typealias
typealias
typealias SecurityRegistry = HashMap<Security.Id,List<Either<Group,Us
val
val
val x:SecurityRegistry = ...
NEXT STEP
NEXT STEP
NEXT STEP
Expressions
Expressions
Expressions
Esspressions
Esspressions
Esspressions
ii
i
Kill statements
Kill statements
Kill statements
fun
fun
fun addWithStatements(a:Int, b:Int):Int {

return
return
return a + b

}

fun
fun
fun addAsExpression(a:Int, b:Int) = a + b
Kill statements
Kill statements
Kill statements
fun
fun
fun addWithStatements(a:Int, b:Int):Int {

return
return
return a + b

}

fun
fun
fun addAsExpression(a:Int, b:Int) = a + b
return
return
return is a younger brother of
is a younger brother of
is a younger brother of GOTO
GOTO
GOTO
Instructions are not funny
Instructions are not funny
Instructions are not funny
sealed
sealed
sealed class
class
class Order(val
val
val sum: Int)
class
class
class Created(s: Int) : Order(s)

class
class
class Paid(s: Int) : Order(s)

class
class
class Delivered(s: Int) : Order(s)
sealed
sealed
sealed class
class
class Order(val
val
val sum: Int)
class
class
class Created(s: Int) : Order(s)

class
class
class Paid(s: Int) : Order(s)

class
class
class Delivered(s: Int) : Order(s)

val
val
val orders = list(

Created(120),

Paid(20),

Delivered(30),

Paid(40)

)
sealed
sealed
sealed class
class
class Order(val
val
val sum: Int)

class
class
class Created(s: Int) : Order(s)

class
class
class Paid(s: Int) : Order(s)

class
class
class Delivered(s: Int) : Order(s)

val
val
val orders = list(

Created(120),

Paid(20),

Delivered(30),

Paid(40)

)

fun
fun
fun impureSum(orders: Seq<Order>): Int {

var
var
var sum = 0

for
for
for (order in
in
in orders) {

when
when
when (order) {

is
is
is Paid -> sum = sum + order.sum

is
is
is Delivered -> sum = sum + order.sum

}

}

return
return
return sum

}

fun
fun
fun main() {

println(impureSum(orders)) //90

}
fun
fun
fun pureSum(orders: Seq<Order>): Int =

orders.foldLeft(0, { accumulator, order ->

when
when
when (order) {

is
is
is Paid -> accumulator + order.sum

is
is
is Delivered -> accumulator + order.sum

is
is
is Created -> accumulator

}

})

fun
fun
fun main() =

println(pureSum(orders)) //90
fun
fun
fun pureSum(orders: Seq<Order>): Int =

orders.foldLeft(0) { accumulator, order ->

when
when
when (order) {

is
is
is Paid -> accumulator + order.sum

is
is
is Delivered -> accumulator + order.sum

is
is
is Created -> accumulator

}

}

fun
fun
fun main() =

println(pureSum(orders)) //90
fun
fun
fun pureSum(orders: Seq<Order>): Int =

orders.foldLeft(0) { accumulator, order ->

when
when
when (order) {

is
is
is Paid -> accumulator + order.sum

is
is
is Delivered -> accumulator + order.sum

is
is
is Created -> accumulator

}

}

fun
fun
fun main() =

println(pureSum(orders)) //90
fold - don't loop
fold - don't loop
fold - don't loop
One day ...
One day ...
One day ...
One day ...
One day ...
One day ...
Business: We have to add new types of orders
Business: We have to add new types of orders
Business: We have to add new types of orders
sealed
sealed
sealed class
class
class Order(val
val
val sum: Int)

class
class
class Created(s: Int) : Order(s)

class
class
class Paid(s: Int) : Order(s)

class
class
class Delivered(s: Int) : Order(s)

//new guy

class
class
class Cancelled(s:Int) : Order(s)

//new guy

class
class
class Archived(s:Int) :Order(s)

val
val
val orders = list(

Created(120),

Paid(20),

Delivered(30),

Paid(40),

Cancelled(20),

Archived(10)

)
fun
fun
fun impureSum(orders: Seq<Order>): Int {

var
var
var sum = 0

for
for
for (order in
in
in orders) {

when
when
when (order) {

is
is
is Paid -> sum = sum + order.sum

is
is
is Delivered -> sum = sum + order.sum

}

}

return
return
return sum //90 - wrong

}
fun
fun
fun impureSum(orders: Seq<Order>): Int =

orders.foldLeft(0) { accumulator, order ->

when
when
when (order) {

// Error: 'when' expression must be exhaustive, 

// add necessary 'is Cancelled', 'is Archived' branches
// or 'else' branch instead

is
is
is Paid -> accumulator + order.sum

is
is
is Delivered -> accumulator + order.sum

is
is
is Created -> accumulator

}

} //wont compile
Compiler is like your BEST friend.
Compiler is like your BEST friend.
Compiler is like your BEST friend.
Best friend:
Best friend:
Best friend: Will tell you the truth even if You do not want to hear
Will tell you the truth even if You do not want to hear
Will tell you the truth even if You do not want to hear
it
it
it
Compiler will
Compiler will
Compiler will tell you that your code will eventually crash on
tell you that your code will eventually crash on
tell you that your code will eventually crash on
production.
production.
production.
if
if
if ,,
, when
when
when,,
, try
try
try etc. are expressions in Kotlin
etc. are expressions in Kotlin
etc. are expressions in Kotlin
use them
use them
use them
fun (a:Int,b:Int) = 

a + if
if
if (b<5) a else
else
else -a
Even More safety
Even More safety
Even More safety
sealed
sealed
sealed class
class
class Order(internal
internal
internal val
val
val sum: Int) {

open
open
open fun
fun
fun income(): Int = sum
fun
fun
fun cancelled() = Cancelled(this
this
this)

}

class
class
class Created(s: Int) : Order(s) {

override
override
override fun
fun
fun income(): Int = 0

fun
fun
fun pay() = Paid(this
this
this)

}

// cannot create Paid without seeing first ordser in Created state 

class
class
class Paid internal
internal
internal constructor
constructor
constructor(order: Created) : Order(order.sum) {

fun
fun
fun deliver() = Delivered(this
this
this)

}

[...]

val
val
val orders = list(

Created(120),

Created(20).pay(),

Created(30).pay().deliver(),

Created(40).pay(),

Created(20).pay().cancelled(),

Created(30).pay().deliver().archive()

)

fun
fun
fun pureSum(orders: Seq<Order>): Int =

orders.foldLeft(0) { accumulator, order ->

accumulator + order.income()

}

fun
fun
fun main() {
fun
fun
fun perfectDelivery() = run {

val
val
val created = Created(25)

val
val
val paid = created.pay()

paid.deliver()

}
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
effects
effects
effects
class
class
class Paid internal
internal
internal constructor
constructor
constructor(order: Created) : Order(order.sum) {

fun
fun
fun deliver() = Delivered(this
this
this).also {

println("delivered")

}

fun
fun
fun deliverFast() = Delivered(this
this
this).also {

println("delivered fast")

}

}
fun
fun
fun perfectDelivery() = run {

val
val
val created = Created(25)

val
val
val paid = created.pay()

paid.deliver()

}
Surprise
Surprise
Surprise
fun
fun
fun doubleDelivery() = run {

val
val
val created = Created(25)

val
val
val paid = created.pay()

paid.deliver()

if
if
if (paid.income() > 20) {

paid.deliverFast()

}

}

fun
fun
fun main() = doubleDelivery()

//delivered

//delivered fast
SIDE EFFECTS DONE PURELY
SIDE EFFECTS DONE PURELY
SIDE EFFECTS DONE PURELY
How to not have surprises (that often)
How to not have surprises (that often)
How to not have surprises (that often)
a fail
a fail
a fail
fun
fun
fun sayIt() = println("I am just dirty side effect")
fun
fun
fun sayItLater() = { println("No side effects")}
fun
fun
fun sayItLater() = { println("No side effects")}

fun
fun
fun main() = run {

sayItLater() //nothing

val
val
val x = sayItLater() // nothing

x() //"No side effects" (there it happens)

}
Back to the problem:
Back to the problem:
Back to the problem:
fun
fun
fun crashDelivery() = run {

val
val
val created = Created(25)

val
val
val paid = created.pay()

paid.deliver()

if
if
if (paid.income() > 20) {

paid.deliverFast()

}

}
Naleśnik == PanCake
Naleśnik == PanCake
Naleśnik == PanCake
class
class
class Naleśnik<out A>(private
private
private val
val
val inside: () -> A) {

fun
fun
fun <B> map(f: (A) -> B) = 

Naleśnik { f(this
this
this.inside()) }

fun
fun
fun <B> flatMap(f: (A) -> Naleśnik<B>): Naleśnik<B> = 

Naleśnik { f(this
this
this.inside()).inside() }

fun
fun
fun unsafeRun(): A = inside() //use with caution

}
sealed
sealed
sealed class
class
class Order(internal
internal
internal val
val
val sum: Int) {

open
open
open fun
fun
fun income(): Int = sum

fun
fun
fun cancelled() = Naleśnik { Cancelled(this
this
this) }

}

class
class
class Created(s: Int) : Order(s) {

override
override
override fun
fun
fun income(): Int = 0

fun
fun
fun pay() = Naleśnik { Paid(this
this
this) }

}

class
class
class Paid internal
internal
internal constructor
constructor
constructor(order: Created) : Order(order.sum) {

fun
fun
fun deliver(): Naleśnik<Delivered> = Naleśnik {

Delivered(this
this
this).also {
println("delivered")

}

}

fun
fun
fun deliverFast(): Naleśnik<Delivered> = Naleśnik {

Delivered(this
this
this).also {
println("delivered fast")

}

}

}
fun
fun
fun crashDelivery():Naleśnik<Delivered> = run {

val
val
val created = Created(25)

val
val
val paid = created.pay()

val
val
val delivered = paid.flatMap { it.deliver() }

paid.flatMap { if
if
if (it.income()> 20) it.deliverFast() else
else
else it.de
}

fun
fun
fun main() {

crashDelivery().unsafeRun()

//delivered fast

}
Naleśnik / pancake - harder to mess side
Naleśnik / pancake - harder to mess side
Naleśnik / pancake - harder to mess side
effects
effects
effects
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
FRAMEWORKS
FRAMEWORKS
Transaction is a Monad
Transaction is a Monad
Transaction is a Monad
class
class
class Transaction<A>(private
private
private val
val
val action: (Connection) -> A) {

fun
fun
fun <B> map ( f: (A)->B) = Transaction { conn -> f(action(conn))}

fun
fun
fun <B> flatMap( f: (A)->Transaction<B>) = 

Transaction { conn -> f(action(conn)).action(conn) }

fun
fun
fun runTransaction(conn:Connection): Either<Exception, A> = run {

val
val
val initialAC = conn.autoCommit

conn.autoCommit = false

try
try
try {

val
val
val res = action(conn)

conn.commit()

Either.right(res)

} catch
catch
catch (e: Exception) {

conn.rollback()

Either.left(e)

} finally
finally
finally {

conn.autoCommit = initialAC

}

}

}
GENERIC SIDE EFFECTS
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
Do not write:
Do not write:
Do not write:
class
class
class Hasiok {

@Resource

val
val
val jdbcConnection: Connection

@Transactional

@Secure

@Cacheable

@Retryable

fun
fun
fun f(p:P) {

//code

}

}
Write like:
Write like:
Write like:
class
class
class Hasiok {

fun
fun
fun enterprisyFunction(x:Int) = Nee.pure(

secure + retryable + cache.of(x) + tx

) {jdbcConnection:Connection ->

//code using jdbcConnection

}

//declaration above means security is checked before retrial

//and retrial is made before cache which happens before transacti
}
FRAMEWORKS
FRAMEWORKS
FRAMEWORKS
Kotlin ktor (web)
arrow-kt, arrow-fx (effects)
Nee (experiemental)
https://github.com/colomboe/KIO
HOW TO PROTECT PURITY
HOW TO PROTECT PURITY
HOW TO PROTECT PURITY
HOW TO PROTECT PURITY
HOW TO PROTECT PURITY
HOW TO PROTECT PURITY
What about discipline
What about discipline
What about discipline
TOOLS
TOOLS
TOOLS
KURE-POTLIN
KURE-POTLIN
KURE-POTLIN
https://github.com/neeffect/kure-potlin
https://github.com/neeffect/kure-potlin
https://github.com/neeffect/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:
ClassDefinition use of object-oriented class active: false
AbstractClassDefinition 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
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
no variables (var)
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
no variables (var)
no loops
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
no variables (var)
no loops
no instructions
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
no variables (var)
no loops
no instructions
no void (Unit)
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
no variables (var)
no loops
no instructions
no void (Unit)
no return
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
no variables (var)
no loops
no instructions
no void (Unit)
no return
no throw
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
no variables (var)
no loops
no instructions
no void (Unit)
no return
no throw
no mercy
PURE CODE NOS
PURE CODE NOS
PURE CODE NOS
no variables (var)
no loops
no instructions
no void (Unit)
no return
no throw
no mercy
with the exception of main
DO YOU NEED FP?
DO YOU NEED FP?
DO YOU NEED FP?
Who needs calculator if all we do is adding
Who needs calculator if all we do is adding
Who needs calculator if all we do is adding
things like
things like
things like 123 + 352
123 + 352
123 + 352
Who needs electronic calc if all we do is
Who needs electronic calc if all we do is
Who needs electronic calc if all we do is
multiplying things like
multiplying things like
multiplying things like 323 *3
323 *3
323 *3
Who needs computer calc if divide and multiply
Who needs computer calc if divide and multiply
Who needs computer calc if divide and multiply
few numbers
few numbers
few numbers
For someone having experience with abacus
For someone having experience with abacus
For someone having experience with abacus
only - this machine is useless
only - this machine is useless
only - this machine is useless
FP ROAD
FP ROAD
FP ROAD
Immutability
Expressions
Type safety
Monads
PROJECT LINKS
PROJECT LINKS
PROJECT LINKS
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 effects for kotlin
springy effects for kotlin
springy effects 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/neeffect/kure-potlin
https://github.com/neeffect/kure-potlin
https://github.com/neeffect/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/neeffect/nee
https://github.com/neeffect/nee
https://github.com/neeffect/nee
https://github.com/neeffect/kotlin-stones
https://github.com/neeffect/kotlin-stones
https://github.com/neeffect/kotlin-stones
SUMMARY
SUMMARY
SUMMARY
FP
FP
FP
SUMMARY
SUMMARY
SUMMARY
FP
FP
FP
The more complex program we write the more
The more complex program we write the more
The more complex program we write the more
it helps
it helps
it helps
SUMMARY
SUMMARY
SUMMARY
FP
FP
FP
The more complex program we write the more
The more complex program we write the more
The more complex program we write the more
it helps
it helps
it helps
It is not a sliver bullet
It is not a sliver bullet
It is not a sliver bullet
SUMMARY
SUMMARY
SUMMARY
FP
FP
FP
The more complex program we write the more
The more complex program we write the more
The more complex program we write the more
it helps
it helps
it helps
It is not a sliver bullet
It is not a sliver bullet
It is not a sliver bullet
It's a long way. But there are many convenient
It's a long way. But there are many convenient
It's a long way. But there are many convenient
steps
steps
steps
SUMMARY
SUMMARY
SUMMARY
FP
FP
FP
The more complex program we write the more
The more complex program we write the more
The more complex program we write the more
it helps
it helps
it helps
It is not a sliver bullet
It is not a sliver bullet
It is not a sliver bullet
It's a long way. But there are many convenient
It's a long way. But there are many convenient
It's a long way. But there are many convenient
steps
steps
steps
Each step is a potential
Each step is a potential
Each step is a potential profit
profit
profit
SUMMARY
SUMMARY
SUMMARY
FP
FP
FP
The more complex program we write the more
The more complex program we write the more
The more complex program we write the more
it helps
it helps
it helps
It is not a sliver bullet
It is not a sliver bullet
It is not a sliver bullet
It's a long way. But there are many convenient
It's a long way. But there are many convenient
It's a long way. But there are many convenient
steps
steps
steps
Each step is a potential
Each step is a potential
Each step is a potential profit
profit
profit
Kotlin is not Scala - but with some
Kotlin is not Scala - but with some
Kotlin is not Scala - but with some
tools/constraints it can be quite pure
tools/constraints it can be quite pure
tools/constraints it can be quite pure

More Related Content

Similar to Pure Kotlin Devoxx PL 2021

G3 Summit 2016 - Taking Advantage of Groovy Annotations
G3 Summit 2016 - Taking Advantage of Groovy AnnotationsG3 Summit 2016 - Taking Advantage of Groovy Annotations
G3 Summit 2016 - Taking Advantage of Groovy Annotations
Iván López Martín
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
BTI360
 
Functional concepts in C#
Functional concepts in C#Functional concepts in C#
Functional concepts in C#
Blend Interactive
 
Kotlin : Happy Development
Kotlin : Happy DevelopmentKotlin : Happy Development
Kotlin : Happy Development
Md Sazzad Islam
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
Codecamp Romania
 
Hey Kotlin, How it works?
Hey Kotlin, How it works?Hey Kotlin, How it works?
Hey Kotlin, How it works?
Chang W. Doh
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
Benjamin Waye
 
Features of Kotlin I find exciting
Features of Kotlin I find excitingFeatures of Kotlin I find exciting
Features of Kotlin I find exciting
Robert MacLean
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
HamletDRC
 
No excuses, switch to kotlin
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlin
Thijs Suijten
 
Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요
Chang W. Doh
 
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018 Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
Codemotion
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
intelliyole
 
Speed up the mobile development process
Speed up the mobile development processSpeed up the mobile development process
Speed up the mobile development process
LeonardoSarra
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
Fabio Collini
 
Kotlin Overview (PT-BR)
Kotlin Overview (PT-BR)Kotlin Overview (PT-BR)
Kotlin Overview (PT-BR)
ThomasHorta
 
Kotlin
KotlinKotlin
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Codemotion
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
Aleksandar Prokopec
 
An Introduction to Scala (2014)
An Introduction to Scala (2014)An Introduction to Scala (2014)
An Introduction to Scala (2014)
William Narmontas
 

Similar to Pure Kotlin Devoxx PL 2021 (20)

G3 Summit 2016 - Taking Advantage of Groovy Annotations
G3 Summit 2016 - Taking Advantage of Groovy AnnotationsG3 Summit 2016 - Taking Advantage of Groovy Annotations
G3 Summit 2016 - Taking Advantage of Groovy Annotations
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
Functional concepts in C#
Functional concepts in C#Functional concepts in C#
Functional concepts in C#
 
Kotlin : Happy Development
Kotlin : Happy DevelopmentKotlin : Happy Development
Kotlin : Happy Development
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
 
Hey Kotlin, How it works?
Hey Kotlin, How it works?Hey Kotlin, How it works?
Hey Kotlin, How it works?
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
 
Features of Kotlin I find exciting
Features of Kotlin I find excitingFeatures of Kotlin I find exciting
Features of Kotlin I find exciting
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
 
No excuses, switch to kotlin
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlin
 
Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요
 
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018 Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
 
Speed up the mobile development process
Speed up the mobile development processSpeed up the mobile development process
Speed up the mobile development process
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
Kotlin Overview (PT-BR)
Kotlin Overview (PT-BR)Kotlin Overview (PT-BR)
Kotlin Overview (PT-BR)
 
Kotlin
KotlinKotlin
Kotlin
 
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
An Introduction to Scala (2014)
An Introduction to Scala (2014)An Introduction to Scala (2014)
An Introduction to Scala (2014)
 

More from Jarek Ratajski

respect-estimates.pdf
respect-estimates.pdfrespect-estimates.pdf
respect-estimates.pdf
Jarek Ratajski
 
Lambda hardcore
Lambda hardcoreLambda hardcore
Lambda hardcore
Jarek Ratajski
 
Transaction is a monad
Transaction is a  monadTransaction is a  monad
Transaction is a monad
Jarek Ratajski
 
Scala to assembly
Scala to assemblyScala to assembly
Scala to assembly
Jarek Ratajski
 
Spring, CDI, Jakarta EE good parts
Spring, CDI, Jakarta EE good partsSpring, CDI, Jakarta EE good parts
Spring, CDI, Jakarta EE good parts
Jarek Ratajski
 
Eta lang Beauty And The Beast
Eta lang Beauty And The Beast Eta lang Beauty And The Beast
Eta lang Beauty And The Beast
Jarek Ratajski
 
Another programming language - jeszcze jeden język
Another programming language - jeszcze jeden językAnother programming language - jeszcze jeden język
Another programming language - jeszcze jeden język
Jarek Ratajski
 
Beauty and the beast - Haskell on JVM
Beauty and the beast  - Haskell on JVMBeauty and the beast  - Haskell on JVM
Beauty and the beast - Haskell on JVM
Jarek Ratajski
 
Fighting null with memes
Fighting null with memesFighting null with memes
Fighting null with memes
Jarek Ratajski
 
Eta
EtaEta
Geecon walking in CODE
Geecon walking in CODEGeecon walking in CODE
Geecon walking in CODE
Jarek Ratajski
 
Scalaworld lambda core hardcore
Scalaworld lambda core hardcoreScalaworld lambda core hardcore
Scalaworld lambda core hardcore
Jarek Ratajski
 
Lambda core
Lambda coreLambda core
Lambda core
Jarek Ratajski
 
[4 dev] lagom
[4 dev] lagom[4 dev] lagom
[4 dev] lagom
Jarek Ratajski
 
Jdd 2016 DROP DATABASE
Jdd 2016 DROP DATABASEJdd 2016 DROP DATABASE
Jdd 2016 DROP DATABASE
Jarek Ratajski
 
DROPDB Galactic story
DROPDB Galactic storyDROPDB Galactic story
DROPDB Galactic story
Jarek Ratajski
 

More from Jarek Ratajski (16)

respect-estimates.pdf
respect-estimates.pdfrespect-estimates.pdf
respect-estimates.pdf
 
Lambda hardcore
Lambda hardcoreLambda hardcore
Lambda hardcore
 
Transaction is a monad
Transaction is a  monadTransaction is a  monad
Transaction is a monad
 
Scala to assembly
Scala to assemblyScala to assembly
Scala to assembly
 
Spring, CDI, Jakarta EE good parts
Spring, CDI, Jakarta EE good partsSpring, CDI, Jakarta EE good parts
Spring, CDI, Jakarta EE good parts
 
Eta lang Beauty And The Beast
Eta lang Beauty And The Beast Eta lang Beauty And The Beast
Eta lang Beauty And The Beast
 
Another programming language - jeszcze jeden język
Another programming language - jeszcze jeden językAnother programming language - jeszcze jeden język
Another programming language - jeszcze jeden język
 
Beauty and the beast - Haskell on JVM
Beauty and the beast  - Haskell on JVMBeauty and the beast  - Haskell on JVM
Beauty and the beast - Haskell on JVM
 
Fighting null with memes
Fighting null with memesFighting null with memes
Fighting null with memes
 
Eta
EtaEta
Eta
 
Geecon walking in CODE
Geecon walking in CODEGeecon walking in CODE
Geecon walking in CODE
 
Scalaworld lambda core hardcore
Scalaworld lambda core hardcoreScalaworld lambda core hardcore
Scalaworld lambda core hardcore
 
Lambda core
Lambda coreLambda core
Lambda core
 
[4 dev] lagom
[4 dev] lagom[4 dev] lagom
[4 dev] lagom
 
Jdd 2016 DROP DATABASE
Jdd 2016 DROP DATABASEJdd 2016 DROP DATABASE
Jdd 2016 DROP DATABASE
 
DROPDB Galactic story
DROPDB Galactic storyDROPDB Galactic story
DROPDB Galactic story
 

Recently uploaded

The Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdfThe Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
kalichargn70th171
 
The Role of DevOps in Digital Transformation.pdf
The Role of DevOps in Digital Transformation.pdfThe Role of DevOps in Digital Transformation.pdf
The Role of DevOps in Digital Transformation.pdf
mohitd6
 
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
campbellclarkson
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
gapen1
 
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
kalichargn70th171
 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
Yara Milbes
 
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Ortus Solutions, Corp
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
ShulagnaSarkar2
 
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
widenerjobeyrl638
 
Going AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applicationsGoing AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applications
Alina Yurenko
 
Stork Product Overview: An AI-Powered Autonomous Delivery Fleet
Stork Product Overview: An AI-Powered Autonomous Delivery FleetStork Product Overview: An AI-Powered Autonomous Delivery Fleet
Stork Product Overview: An AI-Powered Autonomous Delivery Fleet
Vince Scalabrino
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
Tier1 app
 
Boost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management AppsBoost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management Apps
Jhone kinadey
 
TheFutureIsDynamic-BoxLang-CFCamp2024.pdf
TheFutureIsDynamic-BoxLang-CFCamp2024.pdfTheFutureIsDynamic-BoxLang-CFCamp2024.pdf
TheFutureIsDynamic-BoxLang-CFCamp2024.pdf
Ortus Solutions, Corp
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
Maitrey Patel
 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
Pedro J. Molina
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
 
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data PlatformAlluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio, Inc.
 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
kalichargn70th171
 

Recently uploaded (20)

The Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdfThe Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
 
The Role of DevOps in Digital Transformation.pdf
The Role of DevOps in Digital Transformation.pdfThe Role of DevOps in Digital Transformation.pdf
The Role of DevOps in Digital Transformation.pdf
 
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
 
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
 
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
Strengthening Web Development with CommandBox 6: Seamless Transition and Scal...
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
 
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
 
Going AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applicationsGoing AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applications
 
Stork Product Overview: An AI-Powered Autonomous Delivery Fleet
Stork Product Overview: An AI-Powered Autonomous Delivery FleetStork Product Overview: An AI-Powered Autonomous Delivery Fleet
Stork Product Overview: An AI-Powered Autonomous Delivery Fleet
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
 
Boost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management AppsBoost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management Apps
 
TheFutureIsDynamic-BoxLang-CFCamp2024.pdf
TheFutureIsDynamic-BoxLang-CFCamp2024.pdfTheFutureIsDynamic-BoxLang-CFCamp2024.pdf
TheFutureIsDynamic-BoxLang-CFCamp2024.pdf
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
 
bgiolcb
bgiolcbbgiolcb
bgiolcb
 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
 
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data PlatformAlluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
 

Pure Kotlin Devoxx PL 2021

  • 1. DEVOXX PL 2021 DEVOXX PL 2021 DEVOXX PL 2021 PURE KOTLIN PURE KOTLIN PURE KOTLIN
  • 3. Jarek Ratajski Jarek Ratajski Jarek Ratajski working for working for working for Digital Asset Digital Asset Digital Asset This talk does not represent company views, it This talk does not represent company views, it This talk does not represent company views, it is based on personal experience is based on personal experience is based on personal experience and opinions and opinions and opinions
  • 8. AGENDA AGENDA AGENDA Propaganda The road to purity How to stay pure Links, frameworks, examples, disasters
  • 9. PART 1 PART 1 PART 1 FP FP FP
  • 10. PART 1 PART 1 PART 1 FP FP FP FUNCTIONAL PROPAGANDA
  • 11. 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
  • 12.
  • 16. FP PROMISES less errors less code less tests
  • 17. FP PROMISES less errors less code less tests LESS != Nil LESS != Nil LESS != Nil
  • 18. Two hours after deployment Two hours after deployment Two hours after deployment
  • 19. What is functional programming? What is functional programming? What is functional programming? Programming with functions: Programming with functions: Programming with functions: deterministic total pure
  • 20. 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 definition Ok, I have no idea. Just copied this definition Ok, I have no idea. Just copied this definition from John De Goes ;-) from John De Goes ;-) from John De Goes ;-)
  • 21. DETERMINISTIC depend on arguments only always yield same results for the same arguments fun fun fun hello() = "Hello Devoxx Poland" fun fun fun fact(n:Int) = if if if (n<=1) 1 else else else n*fact(n-1) fun fun fun radom() = Math.random()*0.7
  • 22. TOTAL: Yields result/finishes for all possible arguments Yields result/finishes for all possible arguments Yields result/finishes for all possible arguments fun fun fun negate(a:Int):Int = -a fun fun fun radomize(v:String) = "Radom znowu $v" fun fun fun parseInt(t:String):Int = /* whatever */
  • 23. PURE: Leaves no traces. Leaves no traces. Leaves no traces. The only (practical) way to The only (practical) way to The only (practical) way to detect if the function was called is by reading a detect if the function was called is by reading a detect if the function was called is by reading a result. result. result. fun fun fun add(a:Int, b:Int) = a+b [CODE A] val val val x = add(6,3) [OR] val val val x = 9 [CODE B]
  • 24. fun fun fun add(a:Int, b:Int) = a*b //happy debugging fun fun fun add2(a:Int, b:Int) = run { Thread.sleep(a*1000) Thread.sleep(b*1000) return return return a+b } fun fun fun add3(a:Int, b:Int) = (a+b).also { log("was adding something...") }
  • 25. Killer feature of functional programming Killer feature of functional programming Killer feature of functional programming
  • 26. Killer feature of functional programming Killer feature of functional programming Killer feature of functional programming COMPOSABILITY COMPOSABILITY COMPOSABILITY
  • 27. Killer feature of functional programming Killer feature of functional programming Killer feature of functional programming COMPOSABILITY COMPOSABILITY COMPOSABILITY
  • 28. PART 2 PART 2 PART 2 KOTLIN PROPAGANDA KOTLIN PROPAGANDA KOTLIN PROPAGANDA
  • 29. Kotlin killer feature? Kotlin killer feature? Kotlin killer feature?
  • 30. Keyboard used by java developer Keyboard used by java developer Keyboard used by java developer
  • 31. Kotlin Kotlin Kotlin == No more semicolons == No more semicolons == No more semicolons
  • 32. Data class Data class Data class kotlin kotlin kotlin data data data class class class Person( val val val name:String, val val val age:Int, val val val drinking:Boolean = true )
  • 33. public public public final final final class class class Person { @NotNull private private private final final final String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } }
  • 34. public public public final final final class class class Person { @NotNull private private private final final final String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } } val drinking:Boolean = true val drinking:Boolean = true val drinking:Boolean = true
  • 35. public public public final final final class class class Person { @NotNull private private private final final final String String String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String String String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String String String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } public public public Person(@NotNull String String String name, int int int age) { this this this(name, age, true);
  • 36. public public public final final final class class class Person { @NotNull private private private final final final String String String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String String String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String String String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } public public public Person(@NotNull String String String name, int int int age) { this this this(name, age, true); equals and hashCode equals and hashCode equals and hashCode
  • 37. public public public int int int hashCode() { String var10000 = this this this.name; int int int var1 = ((var10000 != null null null ? var10000.hashCode() : 0) * 31 + this this this. return return return var1 + (drinking ? 1 : 0); } public public public boolean boolean boolean equals(@Nullable Object var1) { if if if (this this this != var1) { if if if (var1 instanceof instanceof instanceof Person) { Person var2 = (Person) var1; if if if (Intrinsics.areEqual(this this this.name, var2.name) && this this this.age == var2.age && this this this.drinking == var2.drinking) { return return return true true true; } } return return return false false false; } else else else { return return return true true true; } }
  • 38. public public public int hashCode() { String var10000 = this this this.name; int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this this this. return return return var1 + (drinking ? 1 : 0); } public public public boolean equals(@Nullable Object var1) { if if if (this this this != var1) { if if if (var1 instanceof Person) { Person var2 = (Person) var1; if if if (Intrinsics.areEqual(this this this.name, var2.name) && this this this.age == var2.age && this this this.drinking == var2.drinking) { return return return true; } } return return return false; } else else else { return return return true; } } @NotNull public public public String toString() { return return return "Person(name=" + this this this.name + ", age=" + this this this.age + ", drinking }
  • 39. Back to kotlin Back to kotlin Back to kotlin
  • 40. fun fun fun main() = run { val val val p = Person("irek", 27, true) // }
  • 41. fun fun fun main() = run { val val val p = Person("irek", 27, true) val val val p1 = p.copy(name = "Irek") }
  • 42. fun fun fun main() = run { val val val p = Person("irek", 27, true) val val 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 fun fun main() = run { val val val p = Person("irek", 27, true) val val val p1 = p.copy(name = "Irek") val val val p2 = p1.copy(age = 28) }
  • 44. fun fun fun main() = run { val val val p = Person("irek", 27, true) val val val p1 = p.copy(name = "Irek") val val val p2 = p1.copy(age = 28) val val val p3 = p2.copy(drinking = false) }
  • 45. fun fun fun main() = run { val val val p = Person("irek", 27, true) val val val p1 = p.copy(name = "Irek") val val val p2 = p1.copy(age = 28) val val val p3 = p2.copy(drinking = false) val val val p4 = p3.copy(age = 29, drinking = true) } //Person(name=Zdzich, age=30, drinking=false)
  • 46. fun fun fun main() = run { val val val p = Person("irek", 27, true) val val val p1 = p.copy(name = "Irek") val val val p2 = p1.copy(age = 28) val val val p3 = p2.copy(drinking = false) val val val p4 = p3.copy(age = 29, drinking = true) val val val p5 = p4.copy(name = "Zdzich", age = p4.age+1, drinking = false) println(p3) //Person(name=Irek, age=28, drinking=false) println(p5) //Person(name=Zdzich, age=30, drinking=false) }
  • 47. public public public final final final class class class Person { @NotNull private private private final final final String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } public public public Person(@NotNull String name, int int int age) { this this this(name, age, true true true); } public public public int int int hashCode() { String var10000 = this this this.name; int int int var1 = ((var10000 != null null null ? var10000.hashCode() : 0) * 31 + this this this.age) * 31; return return return var1 + (drinking ? 1 : 0); } public public public boolean boolean boolean equals(@Nullable Object var1) { if if if (this this this != var1) { if if if (var1 instanceof instanceof instanceof Person) { Person var2 = (Person) var1; if if if (Intrinsics.areEqual(this this this.name, var2.name) && this this this.age == var2.age && this this this.drinking == var2.drinking) { return return return true true true; } } return return return false false false; } else else else { return return return true true true; } } @NotNull public public public String toString() { return return return "Person(name=" + this this this.name + ", age=" + this this this.age + ", drinking=" + this this this.drinking + ")"; } @NotNull public public public final final final Person copy(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name");
  • 48. public public public final final final class class class Person { @NotNull private private private final final final String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } public public public Person(@NotNull String name, int int int age) { this this this(name, age, true true true); } public public public int int int hashCode() { String var10000 = this this this.name; int int int var1 = ((var10000 != null null null ? var10000.hashCode() : 0) * 31 + this this this.age) * 31; return return return var1 + (drinking ? 1 : 0); } public public public boolean boolean boolean equals(@Nullable Object var1) { if if if (this this this != var1) { if if if (var1 instanceof instanceof instanceof Person) { Person var2 = (Person) var1; if if if (Intrinsics.areEqual(this this this.name, var2.name) && this this this.age == var2.age && this this this.drinking == var2.drinking) { return return return true true true; } } return return return false false false; } else else else { return return return true true true; } } @NotNull public public public String toString() { return return return "Person(name=" + this this this.name + ", age=" + this this this.age + ", drinking=" + this this this.drinking + ")"; } @NotNull public public public final final final Person copy(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, age, drinking); } @NotNull public public public final final final Person copy(@NotNull String name) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, this this this.age, this this this.drinking); } @NotNull public public public final final final Person copy(int int int age) { return return return new new new Person(this this this.name, age, this this this.drinking); }
  • 49. public public public final final final class class class Person { @NotNull private private private final final final String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } public public public Person(@NotNull String name, int int int age) { this this this(name, age, true true true); } public public public int int int hashCode() { String var10000 = this this this.name; int int int var1 = ((var10000 != null null null ? var10000.hashCode() : 0) * 31 + this this this.age) * 31; return return return var1 + (drinking ? 1 : 0); } public public public boolean boolean boolean equals(@Nullable Object var1) { if if if (this this this != var1) { if if if (var1 instanceof instanceof instanceof Person) { Person var2 = (Person) var1; if if if (Intrinsics.areEqual(this this this.name, var2.name) && this this this.age == var2.age && this this this.drinking == var2.drinking) { return return return true true true; } } return return return false false false; } else else else { return return return true true true; } } @NotNull public public public String toString() { return return return "Person(name=" + this this this.name + ", age=" + this this this.age + ", drinking=" + this this this.drinking + ")"; } @NotNull public public public final final final Person copy(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, age, drinking); } @NotNull public public public final final final Person copy(@NotNull String name) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, this this this.age, this this this.drinking); } @NotNull public public public final final final Person copy(int int int age) { return return return new new new Person(this this this.name, age, this this this.drinking); } almost almost almost
  • 50. public public public final final final class class class Person { @NotNull private private private final final final String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } public public public Person(@NotNull String name, int int int age) { this this this(name, age, true true true); } public public public int int int hashCode() { String var10000 = this this this.name; int int int var1 = ((var10000 != null null null ? var10000.hashCode() : 0) * 31 + this this this.age) * 31; return return return var1 + (drinking ? 1 : 0); } public public public boolean boolean boolean equals(@Nullable Object var1) { if if if (this this this != var1) { if if if (var1 instanceof instanceof instanceof Person) { Person var2 = (Person) var1; if if if (Intrinsics.areEqual(this this this.name, var2.name) && this this this.age == var2.age && this this this.drinking == var2.drinking) { return return return true true true; } } return return return false false false; } else else else { return return return true true true; } } @NotNull public public public String toString() { return return return "Person(name=" + this this this.name + ", age=" + this this this.age + ", drinking=" + this this this.drinking + ")"; } @NotNull public public public final final final Person copy(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, age, drinking); } @NotNull public public public final final final Person copy(@NotNull String name) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, this this this.age, this this this.drinking); } @NotNull public public public final final final Person copy(int int int age) { return return return new new new Person(this this this.name, age, this this this.drinking); } @NotNull public public public final final final Person copy(boolean boolean boolean drinking) { return return return new new new Person(this this this.name, this this this.age, drinking); } @NotNull public public public final final final Person copy(@NotNull String name, int int int age) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, age, this this this.drinking); } @NotNull public public public final final final Person copy(@NotNull String name, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, this this this.age, drinking); } @NotNull
  • 51. public public public final final final class class class Person { @NotNull private private private final final final String name; private private private final final final int int int age; private private private final final final boolean boolean boolean drinking; @NotNull public public public final final final String getName() { return return return this this this.name; } public public public final final final int int int getAge() { return return return this this this.age; } public public public final final final boolean boolean boolean getDrinking() { return return return this this this.drinking; } public public public Person(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); this this this.name = name; this this this.age = age; this this this.drinking = drinking; } public public public Person(@NotNull String name, int int int age) { this this this(name, age, true true true); } public public public int int int hashCode() { String var10000 = this this this.name; int int int var1 = ((var10000 != null null null ? var10000.hashCode() : 0) * 31 + this this this.age) * 31; return return return var1 + (drinking ? 1 : 0); } public public public boolean boolean boolean equals(@Nullable Object var1) { if if if (this this this != var1) { if if if (var1 instanceof instanceof instanceof Person) { Person var2 = (Person) var1; if if if (Intrinsics.areEqual(this this this.name, var2.name) && this this this.age == var2.age && this this this.drinking == var2.drinking) { return return return true true true; } } return return return false false false; } else else else { return return return true true true; } } @NotNull public public public String toString() { return return return "Person(name=" + this this this.name + ", age=" + this this this.age + ", drinking=" + this this this.drinking + ")"; } @NotNull public public public final final final Person copy(@NotNull String name, int int int age, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, age, drinking); } @NotNull public public public final final final Person copy(@NotNull String name) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, this this this.age, this this this.drinking); } @NotNull public public public final final final Person copy(int int int age) { return return return new new new Person(this this this.name, age, this this this.drinking); } @NotNull public public public final final final Person copy(boolean boolean boolean drinking) { return return return new new new Person(this this this.name, this this this.age, drinking); } @NotNull public public public final final final Person copy(@NotNull String name, int int int age) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, age, this this this.drinking); } @NotNull public public public final final final Person copy(@NotNull String name, boolean boolean boolean drinking) { Intrinsics.checkNotNullParameter(name, "name"); return return return new new new Person(name, this this this.age, drinking); } @NotNull 30 semicolons included 30 semicolons included 30 semicolons included
  • 52. data data data class class class Person(val val val name:String, val val val age:Int, val val val drinking:Boolean = true)
  • 53. data data data class class class Person( val val val name:String, val val val age:Int, val val val drinking:Boolean = true )
  • 54. data data data class class class Person( val val val names:List<String>, val val val lastName:String, val val val birthDate:LocalDate, val val val email:Email, val val val address:Address, val val val family:List<Person>, val val val drinking:Boolean = true )
  • 55. In java there are In java there are In java there are records records records but unfortunately as but unfortunately as but unfortunately as for for for java 16 java 16 java 16 there is nothing like there is nothing like there is nothing like .copy(...) .copy(...) .copy(...) yet. yet. yet.
  • 57. data class data class data class Simple immutable record Simple immutable record Simple immutable record
  • 58. PURE CODE RULES PURE CODE RULES PURE CODE RULES
  • 59. The most important rule: The most important rule: The most important rule:
  • 60.
  • 61. The most important rule: The most important rule: The most important rule:
  • 62. Don't be like COVID-19 Don't be like COVID-19 Don't be like COVID-19
  • 63. The most important rule: The most important rule: The most important rule:
  • 64. Don't be like COVID-19 Don't be like COVID-19 Don't be like COVID-19
  • 65. The most important rule: The most important rule: The most important rule:
  • 66. Don't be like COVID-19 Don't be like COVID-19 Don't be like COVID-19 Do not mutate Do not mutate Do not mutate
  • 71. vavr list vavr list vavr list val val val list1 = list(1, 2, 3) val val val list2 = list1.prepend(0) println(list1) println(list2) //List(1, 2, 3) //List(0, 1, 2, 3)
  • 72. kotlin immutable (default list) kotlin immutable (default list) kotlin immutable (default list) val val val list1 = listOf(1, 2, 3) val val val list2 = listOf(0) + list1 // not efficient println(list1) println(list2) //[1, 2, 3] //[0, 1, 2, 3]
  • 73. val val val list1 = listOf(1, 2, 3) val val val list2 = listOf(0) + list1 (list1 as as as MutableList)[1] = -1 println(list1) println(list2) //[1, -1, 3] //[0, 1, 2, 3]
  • 74. java.util.ArrayList java.util.ArrayList java.util.ArrayList mutable by design mutable by design mutable by design val val val list1 = ArrayList(listOf(1,2,3)) for for for (el in in in list1 ) { list1.add(list1.size) } println(list1)
  • 75. Not all Lists are created equal Not all Lists are created equal Not all Lists are created 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 (for (for (for typical typical typical business business business code) code) code)
  • 76. TYPE INFERENCE TYPE INFERENCE TYPE INFERENCE HAVING A TYPE BUT NOT TYPING THE TYPE
  • 77.
  • 78. fun fun fun main() { val val val x = "Devoxx Poland" }
  • 79. val variableName : OptionalType = ... val variableName : OptionalType = ... val variableName : OptionalType = ... class class class A(val val val fieldAndConstructorArf:B, onlyArg:String) { val val val fieldInitializedInClass = onlyArg+"_suffix" fun fun fun a(arg:Int):String {// :String not needed val val val variable = "$arg and $fieldInitializedInClass" val val val other:String = variable //:String not needed return return return other } }
  • 80. val variableName : OptionalType = ... val variableName : OptionalType = ... val variableName : OptionalType = ... class class class A(val val val fieldAndConstructorArf:B, onlyArg:String) { val val val fieldInitializedInClass = onlyArg+"_suffix" fun fun fun a(arg:Int):String {// :String not needed val val val variable = "$arg and $fieldInitializedInClass" val val val other:String = variable //:String not needed return return return other } } one simple syntax rule - fits everywhere one simple syntax rule - fits everywhere one simple syntax rule - fits everywhere
  • 81. Type inference means type safety Type inference means type safety Type inference means type safety
  • 82. Type inference means type safety Type inference means type safety Type inference means type safety doubts? doubts? doubts?
  • 83. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (safer)?
  • 84. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (safer)? at least 12 characters
  • 85. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (safer)? at least 12 characters must include upper, lower case, digit and special character
  • 86. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (safer)? at least 12 characters must include upper, lower case, digit and special character must be changed weekly
  • 87. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (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
  • 88. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (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
  • 89. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (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
  • 90. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (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
  • 91. Which password policy is better (safer)? Which password policy is better (safer)? Which password policy is better (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
  • 93. typealias typealias typealias SecurityRegistry = HashMap<Security.Id,List<Either<Group,Us val val val x:SecurityRegistry = ...
  • 94. NEXT STEP NEXT STEP NEXT STEP Expressions Expressions Expressions
  • 96. ii i
  • 97. Kill statements Kill statements Kill statements fun fun fun addWithStatements(a:Int, b:Int):Int { return return return a + b } fun fun fun addAsExpression(a:Int, b:Int) = a + b
  • 98. Kill statements Kill statements Kill statements fun fun fun addWithStatements(a:Int, b:Int):Int { return return return a + b } fun fun fun addAsExpression(a:Int, b:Int) = a + b return return return is a younger brother of is a younger brother of is a younger brother of GOTO GOTO GOTO
  • 99. Instructions are not funny Instructions are not funny Instructions are not funny
  • 100. sealed sealed sealed class class class Order(val val val sum: Int) class class class Created(s: Int) : Order(s) class class class Paid(s: Int) : Order(s) class class class Delivered(s: Int) : Order(s)
  • 101. sealed sealed sealed class class class Order(val val val sum: Int) class class class Created(s: Int) : Order(s) class class class Paid(s: Int) : Order(s) class class class Delivered(s: Int) : Order(s) val val val orders = list( Created(120), Paid(20), Delivered(30), Paid(40) )
  • 102. sealed sealed sealed class class class Order(val val val sum: Int) class class class Created(s: Int) : Order(s) class class class Paid(s: Int) : Order(s) class class class Delivered(s: Int) : Order(s) val val val orders = list( Created(120), Paid(20), Delivered(30), Paid(40) ) fun fun fun impureSum(orders: Seq<Order>): Int { var var var sum = 0 for for for (order in in in orders) { when when when (order) { is is is Paid -> sum = sum + order.sum is is is Delivered -> sum = sum + order.sum } } return return return sum } fun fun fun main() { println(impureSum(orders)) //90 }
  • 103. fun fun fun pureSum(orders: Seq<Order>): Int = orders.foldLeft(0, { accumulator, order -> when when when (order) { is is is Paid -> accumulator + order.sum is is is Delivered -> accumulator + order.sum is is is Created -> accumulator } }) fun fun fun main() = println(pureSum(orders)) //90
  • 104. fun fun fun pureSum(orders: Seq<Order>): Int = orders.foldLeft(0) { accumulator, order -> when when when (order) { is is is Paid -> accumulator + order.sum is is is Delivered -> accumulator + order.sum is is is Created -> accumulator } } fun fun fun main() = println(pureSum(orders)) //90
  • 105. fun fun fun pureSum(orders: Seq<Order>): Int = orders.foldLeft(0) { accumulator, order -> when when when (order) { is is is Paid -> accumulator + order.sum is is is Delivered -> accumulator + order.sum is is is Created -> accumulator } } fun fun fun main() = println(pureSum(orders)) //90 fold - don't loop fold - don't loop fold - don't loop
  • 106. One day ... One day ... One day ...
  • 107.
  • 108. One day ... One day ... One day ...
  • 109. Business: We have to add new types of orders Business: We have to add new types of orders Business: We have to add new types of orders
  • 110. sealed sealed sealed class class class Order(val val val sum: Int) class class class Created(s: Int) : Order(s) class class class Paid(s: Int) : Order(s) class class class Delivered(s: Int) : Order(s) //new guy class class class Cancelled(s:Int) : Order(s) //new guy class class class Archived(s:Int) :Order(s) val val val orders = list( Created(120), Paid(20), Delivered(30), Paid(40), Cancelled(20), Archived(10) )
  • 111. fun fun fun impureSum(orders: Seq<Order>): Int { var var var sum = 0 for for for (order in in in orders) { when when when (order) { is is is Paid -> sum = sum + order.sum is is is Delivered -> sum = sum + order.sum } } return return return sum //90 - wrong }
  • 112. fun fun fun impureSum(orders: Seq<Order>): Int = orders.foldLeft(0) { accumulator, order -> when when when (order) { // Error: 'when' expression must be exhaustive, // add necessary 'is Cancelled', 'is Archived' branches // or 'else' branch instead is is is Paid -> accumulator + order.sum is is is Delivered -> accumulator + order.sum is is is Created -> accumulator } } //wont compile
  • 113. Compiler is like your BEST friend. Compiler is like your BEST friend. Compiler is like your BEST friend. Best friend: Best friend: Best friend: Will tell you the truth even if You do not want to hear Will tell you the truth even if You do not want to hear Will tell you the truth even if You do not want to hear it it it Compiler will Compiler will Compiler will tell you that your code will eventually crash on tell you that your code will eventually crash on tell you that your code will eventually crash on production. production. production.
  • 114. if if if ,, , when when when,, , try try try etc. are expressions in Kotlin etc. are expressions in Kotlin etc. are expressions in Kotlin use them use them use them fun (a:Int,b:Int) = a + if if if (b<5) a else else else -a
  • 115. Even More safety Even More safety Even More safety
  • 116. sealed sealed sealed class class class Order(internal internal internal val val val sum: Int) { open open open fun fun fun income(): Int = sum fun fun fun cancelled() = Cancelled(this this this) } class class class Created(s: Int) : Order(s) { override override override fun fun fun income(): Int = 0 fun fun fun pay() = Paid(this this this) } // cannot create Paid without seeing first ordser in Created state class class class Paid internal internal internal constructor constructor constructor(order: Created) : Order(order.sum) { fun fun fun deliver() = Delivered(this this this) } [...] val val val orders = list( Created(120), Created(20).pay(), Created(30).pay().deliver(), Created(40).pay(), Created(20).pay().cancelled(), Created(30).pay().deliver().archive() ) fun fun fun pureSum(orders: Seq<Order>): Int = orders.foldLeft(0) { accumulator, order -> accumulator + order.income() } fun fun fun main() {
  • 117. fun fun fun perfectDelivery() = run { val val val created = Created(25) val val val paid = created.pay() paid.deliver() }
  • 119. SIDE EFFECTS SIDE EFFECTS SIDE EFFECTS Functional programming is all about side Functional programming is all about side Functional programming is all about side effects effects effects
  • 120. class class class Paid internal internal internal constructor constructor constructor(order: Created) : Order(order.sum) { fun fun fun deliver() = Delivered(this this this).also { println("delivered") } fun fun fun deliverFast() = Delivered(this this this).also { println("delivered fast") } }
  • 121. fun fun fun perfectDelivery() = run { val val val created = Created(25) val val val paid = created.pay() paid.deliver() }
  • 122. Surprise Surprise Surprise fun fun fun doubleDelivery() = run { val val val created = Created(25) val val val paid = created.pay() paid.deliver() if if if (paid.income() > 20) { paid.deliverFast() } } fun fun fun main() = doubleDelivery() //delivered //delivered fast
  • 123. SIDE EFFECTS DONE PURELY SIDE EFFECTS DONE PURELY SIDE EFFECTS DONE PURELY How to not have surprises (that often) How to not have surprises (that often) How to not have surprises (that often)
  • 124. a fail a fail a fail fun fun fun sayIt() = println("I am just dirty side effect")
  • 125. fun fun fun sayItLater() = { println("No side effects")}
  • 126. fun fun fun sayItLater() = { println("No side effects")} fun fun fun main() = run { sayItLater() //nothing val val val x = sayItLater() // nothing x() //"No side effects" (there it happens) }
  • 127. Back to the problem: Back to the problem: Back to the problem: fun fun fun crashDelivery() = run { val val val created = Created(25) val val val paid = created.pay() paid.deliver() if if if (paid.income() > 20) { paid.deliverFast() } }
  • 128. Naleśnik == PanCake Naleśnik == PanCake Naleśnik == PanCake
  • 129.
  • 130. class class class Naleśnik<out A>(private private private val val val inside: () -> A) { fun fun fun <B> map(f: (A) -> B) = Naleśnik { f(this this this.inside()) } fun fun fun <B> flatMap(f: (A) -> Naleśnik<B>): Naleśnik<B> = Naleśnik { f(this this this.inside()).inside() } fun fun fun unsafeRun(): A = inside() //use with caution }
  • 131. sealed sealed sealed class class class Order(internal internal internal val val val sum: Int) { open open open fun fun fun income(): Int = sum fun fun fun cancelled() = Naleśnik { Cancelled(this this this) } } class class class Created(s: Int) : Order(s) { override override override fun fun fun income(): Int = 0 fun fun fun pay() = Naleśnik { Paid(this this this) } } class class class Paid internal internal internal constructor constructor constructor(order: Created) : Order(order.sum) { fun fun fun deliver(): Naleśnik<Delivered> = Naleśnik { Delivered(this this this).also { println("delivered") } } fun fun fun deliverFast(): Naleśnik<Delivered> = Naleśnik { Delivered(this this this).also { println("delivered fast") } } }
  • 132. fun fun fun crashDelivery():Naleśnik<Delivered> = run { val val val created = Created(25) val val val paid = created.pay() val val val delivered = paid.flatMap { it.deliver() } paid.flatMap { if if if (it.income()> 20) it.deliverFast() else else else it.de } fun fun fun main() { crashDelivery().unsafeRun() //delivered fast }
  • 133. Naleśnik / pancake - harder to mess side Naleśnik / pancake - harder to mess side Naleśnik / pancake - harder to mess side effects effects effects
  • 134. Naleśnik > Burrito Naleśnik > Burrito Naleśnik > Burrito
  • 135. Naleśnik Naleśnik Naleśnik == IO (Monad) == IO (Monad) == IO (Monad)
  • 136. IO <A> IO <A> IO <A> ~= ~= ~= Mono<A> Mono<A> Mono<A>
  • 137. in in in arrow-fx arrow-fx arrow-fx IO<A> IO<A> IO<A> == == == suspend () -> A suspend () -> A suspend () -> A
  • 139. Transaction is a Monad Transaction is a Monad Transaction is a Monad class class class Transaction<A>(private private private val val val action: (Connection) -> A) { fun fun fun <B> map ( f: (A)->B) = Transaction { conn -> f(action(conn))} fun fun fun <B> flatMap( f: (A)->Transaction<B>) = Transaction { conn -> f(action(conn)).action(conn) } fun fun fun runTransaction(conn:Connection): Either<Exception, A> = run { val val val initialAC = conn.autoCommit conn.autoCommit = false try try try { val val val res = action(conn) conn.commit() Either.right(res) } catch catch catch (e: Exception) { conn.rollback() Either.left(e) } finally finally finally { conn.autoCommit = initialAC } } }
  • 140. GENERIC SIDE EFFECTS IO<R,E,A> IO<R,E,A> IO<R,E,A> R - environment (dependencies) E - error (not only exception) A - result (business)
  • 142. 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
  • 143. Do not write: Do not write: Do not write: class class class Hasiok { @Resource val val val jdbcConnection: Connection @Transactional @Secure @Cacheable @Retryable fun fun fun f(p:P) { //code } }
  • 144. Write like: Write like: Write like: class class class Hasiok { fun fun fun enterprisyFunction(x:Int) = Nee.pure( secure + retryable + cache.of(x) + tx ) {jdbcConnection:Connection -> //code using jdbcConnection } //declaration above means security is checked before retrial //and retrial is made before cache which happens before transacti }
  • 145. FRAMEWORKS FRAMEWORKS FRAMEWORKS Kotlin ktor (web) arrow-kt, arrow-fx (effects) Nee (experiemental) https://github.com/colomboe/KIO
  • 146. HOW TO PROTECT PURITY HOW TO PROTECT PURITY HOW TO PROTECT PURITY
  • 147. HOW TO PROTECT PURITY HOW TO PROTECT PURITY HOW TO PROTECT PURITY
  • 148. What about discipline What about discipline What about discipline
  • 149.
  • 152. Plugin for Plugin for Plugin for detekt detekt detekt
  • 153. 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: ClassDefinition use of object-oriented class active: false AbstractClassDefinition 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
  • 154. PURE CODE NOS PURE CODE NOS PURE CODE NOS
  • 155. PURE CODE NOS PURE CODE NOS PURE CODE NOS no variables (var)
  • 156. PURE CODE NOS PURE CODE NOS PURE CODE NOS no variables (var) no loops
  • 157. PURE CODE NOS PURE CODE NOS PURE CODE NOS no variables (var) no loops no instructions
  • 158. PURE CODE NOS PURE CODE NOS PURE CODE NOS no variables (var) no loops no instructions no void (Unit)
  • 159. PURE CODE NOS PURE CODE NOS PURE CODE NOS no variables (var) no loops no instructions no void (Unit) no return
  • 160. PURE CODE NOS PURE CODE NOS PURE CODE NOS no variables (var) no loops no instructions no void (Unit) no return no throw
  • 161. PURE CODE NOS PURE CODE NOS PURE CODE NOS no variables (var) no loops no instructions no void (Unit) no return no throw no mercy
  • 162. PURE CODE NOS PURE CODE NOS PURE CODE NOS no variables (var) no loops no instructions no void (Unit) no return no throw no mercy with the exception of main
  • 163. DO YOU NEED FP? DO YOU NEED FP? DO YOU NEED FP?
  • 164.
  • 165.
  • 166. Who needs calculator if all we do is adding Who needs calculator if all we do is adding Who needs calculator if all we do is adding things like things like things like 123 + 352 123 + 352 123 + 352
  • 167.
  • 168. Who needs electronic calc if all we do is Who needs electronic calc if all we do is Who needs electronic calc if all we do is multiplying things like multiplying things like multiplying things like 323 *3 323 *3 323 *3
  • 169.
  • 170. Who needs computer calc if divide and multiply Who needs computer calc if divide and multiply Who needs computer calc if divide and multiply few numbers few numbers few numbers
  • 171. For someone having experience with abacus For someone having experience with abacus For someone having experience with abacus only - this machine is useless only - this machine is useless only - this machine is useless
  • 172. FP ROAD FP ROAD FP ROAD Immutability Expressions Type safety Monads
  • 173. PROJECT LINKS PROJECT LINKS PROJECT LINKS 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 effects for kotlin springy effects for kotlin springy effects 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/neeffect/kure-potlin https://github.com/neeffect/kure-potlin https://github.com/neeffect/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/neeffect/nee https://github.com/neeffect/nee https://github.com/neeffect/nee https://github.com/neeffect/kotlin-stones https://github.com/neeffect/kotlin-stones https://github.com/neeffect/kotlin-stones
  • 174.
  • 176.
  • 177. SUMMARY SUMMARY SUMMARY FP FP FP The more complex program we write the more The more complex program we write the more The more complex program we write the more it helps it helps it helps
  • 178.
  • 179. SUMMARY SUMMARY SUMMARY FP FP FP The more complex program we write the more The more complex program we write the more The more complex program we write the more it helps it helps it helps It is not a sliver bullet It is not a sliver bullet It is not a sliver bullet
  • 180.
  • 181. SUMMARY SUMMARY SUMMARY FP FP FP The more complex program we write the more The more complex program we write the more The more complex program we write the more it helps it helps it helps It is not a sliver bullet It is not a sliver bullet It is not a sliver bullet It's a long way. But there are many convenient It's a long way. But there are many convenient It's a long way. But there are many convenient steps steps steps
  • 182.
  • 183. SUMMARY SUMMARY SUMMARY FP FP FP The more complex program we write the more The more complex program we write the more The more complex program we write the more it helps it helps it helps It is not a sliver bullet It is not a sliver bullet It is not a sliver bullet It's a long way. But there are many convenient It's a long way. But there are many convenient It's a long way. But there are many convenient steps steps steps Each step is a potential Each step is a potential Each step is a potential profit profit profit
  • 184.
  • 185. SUMMARY SUMMARY SUMMARY FP FP FP The more complex program we write the more The more complex program we write the more The more complex program we write the more it helps it helps it helps It is not a sliver bullet It is not a sliver bullet It is not a sliver bullet It's a long way. But there are many convenient It's a long way. But there are many convenient It's a long way. But there are many convenient steps steps steps Each step is a potential Each step is a potential Each step is a potential profit profit profit
  • 186. Kotlin is not Scala - but with some Kotlin is not Scala - but with some Kotlin is not Scala - but with some tools/constraints it can be quite pure tools/constraints it can be quite pure tools/constraints it can be quite pure