SlideShare une entreprise Scribd logo
1  sur  140
Télécharger pour lire hors ligne
PURE KOTLIN
PURE KOTLIN
PURE KOTLIN
Kod/linki:
Kod/linki:
Kod/linki:
AGENDA
AGENDA
AGENDA
AGENDA
AGENDA
AGENDA
Propaganda
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
Frameworks
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
Frameworks
Rules
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
Frameworks
Rules
Propaganda
AGENDA
AGENDA
AGENDA
Propaganda
Propaganda
The road to purity
Frameworks
Rules
Propaganda
Questions, answers, examples,
demos, disasters
PART 1
PART 1
PART 1
FP
FP
FP
PART 1
PART 1
PART 1
FP
FP
FP
FUNCTIONAL PROPAGANDA
PART 1
PART 1
PART 1
FP
FP
FP
FUNCTIONAL PROPAGANDA
also known as
also known as
also known as Functional Programming
Functional Programming
Functional Programming
FP PROMISES
FP PROMISES
less errors
FP PROMISES
less errors
less code
FP PROMISES
less errors
less code
less tests
FP PROMISES
less errors
less code
less tests
LESS != Nil
LESS != Nil
LESS != Nil
Two hours after deployment
Two hours after deployment
Two hours after deployment
1999 I switched from C++ to Java
1999 I switched from C++ to Java
1999 I switched from C++ to Java
Life is too short for malloc
Life is too short for malloc
Life is too short for malloc
2016 - slowly leaving Java away
2016 - slowly leaving Java away
2016 - slowly leaving Java away
I am too old to mutate
I am too old to mutate
I am too old to mutate
What is functional programming?
What is functional programming?
What is functional programming?
Programming with functions:
Programming with functions:
Programming with functions:
deterministic
total
pure
What is functional programming?
What is functional programming?
What is functional programming?
Programming with functions:
Programming with functions:
Programming with functions:
deterministic
total
pure
Ok, I have no idea. Just copied this de nition
Ok, I have no idea. Just copied this de nition
Ok, I have no idea. Just copied this de nition
from John De Goes ;-)
from John De Goes ;-)
from John De Goes ;-)
DETERMINISTIC
depend on arguments only
always yield same results for the same
arguments
fun hello() = "Hello Jug"
fun fact(n:Int) = if (n<=1) 1 else n*fact(n-1)
fun radom() = Math.random()*0.7
TOTAL:
Yields result/ nishes for all possible arguments
Yields result/ nishes for all possible arguments
Yields result/ nishes for all possible arguments
fun negate(a:Int):Int = -a
fun radomize(v:String) = "Radom znowu $v"
fun parseInt(t:String):Int = /* whatever */
PURE:
Leaves no traces. The only (practical) way to
Leaves no traces. The only (practical) way to
Leaves no traces. The only (practical) way to
detect the function was called is by reading a
detect the function was called is by reading a
detect the function was called is by reading a
result.
result.
result.
fun add(a:Int, b:Int) = a+b
[CODE A]
val x = add(6,3) [OR] val x = 9
[CODE B]
fun add(a:Int, b:Int) = a*b //happy debugging
fun add2(a:Int, b:Int) = run {
Thread.sleep(a*1000)
Thread.sleep(b*1000)
return a+b
}
fun add3(a:Int, b:Int) = (a+b).also {
log("was adding something in Kielce")
}
Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
Killer feature of functional programming
COMPOSABILITY
COMPOSABILITY
COMPOSABILITY
PART 2
PART 2
PART 2
KOTLIN PROPAGANDA
KOTLIN PROPAGANDA
KOTLIN PROPAGANDA
Kotlin killer feature?
Kotlin killer feature?
Kotlin killer feature?
No semicolon
No semicolon
No semicolon
Data class
Data class
Data class
kotlin
kotlin
kotlin
data class Person(
val name:String,
val age:Int,
val drinking:Boolean = true
)
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this name = name;
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this name = name;
val drinking:Boolean = true
val drinking:Boolean = true
val drinking:Boolean = true
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this name = name;
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this name = name;
equals and hashCode
equals and hashCode
equals and hashCode
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name)
&& this.age == var2.age
&& this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name)
&& this.age == var2.age
&& this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
Back to kotlin
Back to kotlin
Back to kotlin
fun main() = run {
val p = Person("irek", 27, true)
//
}
fun main() = run {
val p = Person("irek", 27, true)
val p1 = p.copy(name = "Irek")
println(p) //Person(name=irek, age=27, drinking=true)
println(p1) //Person(name=Irek, age=27, drinking=true)
}
fun main() = run {
val p = Person("irek", 27, true)
val p1 = p.copy(name = "Irek")
val p2 = p1.copy(age = 28)
val p3 = p2.copy(drinking = false)
val p4 = p3.copy(age = 29, drinking = true)
val p5 = p4.copy(name = "Zdzich", age = p4.age+1, drinking = fals
println(p5)
}
//Person(name=Zdzich, age=30, drinking=false)
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", drinking=" + this.drinking + ")";
}
@NotNull
public final Person copy(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, drinking);
}
@NotNull
public final Person copy(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this age, this drinking);
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", drinking=" + this.drinking + ")";
}
@NotNull
public final Person copy(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, drinking);
}
@NotNull
public final Person copy(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this age, this drinking);
almost
almost
almost
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", drinking=" + this.drinking + ")";
}
@NotNull
public final Person copy(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, drinking);
}
@NotNull
public final Person copy(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this.age, this.drinking);
}
@NotNull
public final Person copy(int age) {
return new Person(this.name, age, this.drinking);
}
@NotNull
public final Person copy(boolean drinking) {
return new Person(this.name, this.age, drinking);
}
@NotNull
public final Person copy(@NotNull String name, int age) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, this.drinking);
}
@NotNull
public final Person copy(@NotNull String name, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this.age, drinking);
}
@NotNull
public final Person copy(int age, boolean drinking) {
return new Person(this.name, age, drinking);
}
}
public final class Person {
@NotNull
private final String name;
private final int age;
private final boolean drinking;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final boolean getDrinking() {
return this.drinking;
}
public Person(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
this.name = name;
this.age = age;
this.drinking = drinking;
}
public Person(@NotNull String name, int age) {
this(name, age, true);
}
public int hashCode() {
String var10000 = this.name;
int var1 = ((var10000 != null ? var10000.hashCode() : 0) * 31 + this.age) * 31;
return var1 + (drinking ? 1 : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Person) {
Person var2 = (Person) var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.drinking == var2.drinking) {
return true;
}
}
return false;
} else {
return true;
}
}
@NotNull
public String toString() {
return "Person(name=" + this.name + ", age=" + this.age + ", drinking=" + this.drinking + ")";
}
@NotNull
public final Person copy(@NotNull String name, int age, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, drinking);
}
@NotNull
public final Person copy(@NotNull String name) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this.age, this.drinking);
}
@NotNull
public final Person copy(int age) {
return new Person(this.name, age, this.drinking);
}
@NotNull
public final Person copy(boolean drinking) {
return new Person(this.name, this.age, drinking);
}
@NotNull
public final Person copy(@NotNull String name, int age) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, age, this.drinking);
}
@NotNull
public final Person copy(@NotNull String name, boolean drinking) {
Intrinsics.checkNotNullParameter(name, "name");
return new Person(name, this.age, drinking);
}
@NotNull
public final Person copy(int age, boolean drinking) {
return new Person(this.name, age, drinking);
}
}
30 semicolons included
30 semicolons included
30 semicolons included
data class Person(val name:String, val age:Int, val drinking:Boolean = true)
data class Person(
val name:String,
val age:Int,
val drinking:Boolean = true
)
data class Person(
val names:List<String>,
val lastName:String,
val birthDate:LocalDate,
val email:Email,
val address:Address,
val family:List<Person>,
val drinking:Boolean = true
)
Unfortunately,
Unfortunately,
Unfortunately, copy
copy
copy is not yet included (as of
is not yet included (as of
is not yet included (as of
java 16)
java 16)
java 16) in
in
in java records
java records
java records
data class
data class
data class
data class
data class
data class
simple to use immutable record
simple to use immutable record
simple to use immutable record
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
First step on the road to safety (and stress free
First step on the road to safety (and stress free
First step on the road to safety (and stress free
weekends)
weekends)
weekends)
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
First step on the road to safety (and stress free
First step on the road to safety (and stress free
First step on the road to safety (and stress free
weekends)
weekends)
weekends)
immutable records, objects
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
First step on the road to safety (and stress free
First step on the road to safety (and stress free
First step on the road to safety (and stress free
weekends)
weekends)
weekends)
immutable records, objects
immutable data structures
IMMUTABILITY
IMMUTABILITY
IMMUTABILITY
First step on the road to safety (and stress free
First step on the road to safety (and stress free
First step on the road to safety (and stress free
weekends)
weekends)
weekends)
immutable records, objects
immutable data structures
vavr list
vavr list
vavr list
val list1 = list(1, 2, 3)
val list2 = list1.prepend(0)
println(list1)
println(list2)
//List(1, 2, 3)
//List(0, 1, 2, 3)
kotlin immutable (default list)
kotlin immutable (default list)
kotlin immutable (default list)
val list1 = listOf(1, 2, 3)
val list2 = listOf(0)+ list1 // not efficient
println(list1)
println(list2)
//[1, 2, 3]
//[0, 1, 2, 3]
val list1 = listOf(1, 2, 3)
val list2 = listOf(0)+ list1
(list1 as MutableList)[1] = -1
println(list1)
println(list2)
//[1, -1, 3]
//[0, 1, 2, 3]
java.util.ArrayList
java.util.ArrayList
java.util.ArrayList a total disaster
a total disaster
a total disaster
val list1 = ArrayList(listOf(1,2,3))
for (el in list1 ) {
list1.add(list1.size)
}
println(list1)
Not all lists are born equal
Not all lists are born equal
Not all lists are born equal
io.vavr.collection.List
io.vavr.collection.List
io.vavr.collection.List >
>
>
kotlin.ImmutableList
kotlin.ImmutableList
kotlin.ImmutableList >
>
> java.util.List
java.util.List
java.util.List
TYPE INFERENCE
TYPE INFERENCE
TYPE INFERENCE
A small step for a man, but an average one for
A small step for a man, but an average one for
A small step for a man, but an average one for
a dwarf
a dwarf
a dwarf
fun main() {
val x = "Hello Kielce JUG"
}
class A(val fieldAndConstructorArf:B, onlyArg:String) {
val fieldInitializedInClass = onlyArg+"_suffix"
fun a(arg:Int):String {// :String not needed
val variable = "$arg and $fieldInitializedInClass"
val other:String = variable //:String not needed
return other
}
}
class A(val fieldAndConstructorArf:B, onlyArg:String) {
val fieldInitializedInClass = onlyArg+"_suffix"
fun a(arg:Int):String {// :String not needed
val variable = "$arg and $fieldInitializedInClass"
val other:String = variable //:String not needed
return other
}
}
one rule (about val)
one rule (about val)
one rule (about val) ts everywhere
ts everywhere
ts everywhere
Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
Type inference means type safety !!!
any doubts?
any doubts?
any doubts?
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
or
or
or
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
or
or
or
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
or
or
or
Which password policy is safer?
Which password policy is safer?
Which password policy is safer?
at least 12 characters
must include upper, lower case, digit and
special character
must be changed weekly
must be not like recent 20 passwords
or
or
or
val x:HashMap<Security.Id,List<Either<Group,User>>> = ...
typealias SecurityRegistry = HashMap<Security.Id,List<Either<G
val x:SecurityRegistry = ...
NEXT STEP
NEXT STEP
NEXT STEP
Expressions
Expressions
Expressions
Esspressions
Esspressions
Esspressions
ii
i
Kill statements
Kill statements
Kill statements
fun addWithStatements(a:Int, b:Int):Int {
return a + b
}
fun addAsExpression(a:Int, b:Int) = a + b
Kill statements
Kill statements
Kill statements
fun addWithStatements(a:Int, b:Int):Int {
return a + b
}
fun addAsExpression(a:Int, b:Int) = a + b
return
return
return is younger brother of
is younger brother of
is younger brother of GOTO
GOTO
GOTO
Why statements are cool? A long example.
Why statements are cool? A long example.
Why statements are cool? A long example.
sealed class Order(val sum: Int)
class Created(s: Int) : Order(s)
class Paid(s: Int) : Order(s)
class Delivered(s: Int) : Order(s)
sealed class Order(val sum: Int)
class Created(s: Int) : Order(s)
class Paid(s: Int) : Order(s)
class Delivered(s: Int) : Order(s)
val orders = list(
Created(120),
Paid(20),
Delivered(30),
Paid(40)
)
sealed class Order(val sum: Int)
class Created(s: Int) : Order(s)
class Paid(s: Int) : Order(s)
class Delivered(s: Int) : Order(s)
val orders = list(
Created(120),
Paid(20),
Delivered(30),
Paid(40)
)
fun impureSum(orders: Seq<Order>): Int {
var sum = 0
for (order in orders) {
when (order) {
is Paid -> sum = sum + order.sum
is Delivered -> sum = sum + order.sum
}
}
return sum
}
fun main() {
println(impureSum(orders)) //90
}
fun pureSum(orders: Seq<Order>): Int =
orders.foldLeft(0, { accumulator, order ->
when (order) {
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
})
fun main() =
println(pureSum(orders)) //90
fun pureSum(orders: Seq<Order>): Int =
orders.foldLeft(0) { accumulator, order ->
when (order) {
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
}
fun main() =
println(pureSum(orders)) //90
fun pureSum(orders: Seq<Order>): Int =
orders.foldLeft(0) { accumulator, order ->
when (order) {
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
}
fun main() =
println(pureSum(orders)) //90
fold - don't loop
fold - don't loop
fold - don't loop
sealed class Order(val sum: Int)
class Created(s: Int) : Order(s)
class Paid(s: Int) : Order(s)
class Delivered(s: Int) : Order(s)
class Cancelled(s:Int) : Order(s)
class Archived(s:Int) :Order(s)
val orders = list(
Created(120),
Paid(20),
Delivered(30),
Paid(40),
Cancelled(20),
Archived(10)
)
fun impureSum(orders: Seq<Order>): Int {
var sum = 0
for (order in orders) {
when (order) {
is Paid -> sum = sum + order.sum
is Delivered -> sum = sum + order.sum
}
}
return sum //90 - wrong
}
fun impureSum(orders: Seq<Order>): Int =
orders.foldLeft(0) { accumulator, order ->
when (order) {
// Error: 'when' expression must be exhaustive,
// add necessary 'is Cancelled', 'is Archived' br
// or 'else' branch instead
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
} //wont compile
fun impureSum(orders: Seq<Order>): Int =
orders.foldLeft(0) { accumulator, order ->
when (order) {
// Error: 'when' expression must be exhaustive,
// add necessary 'is Cancelled', 'is Archived' br
// or 'else' branch instead
is Paid -> accumulator + order.sum
is Delivered -> accumulator + order.sum
is Created -> accumulator
}
} //wont compile
Compilation error is your friend
Compilation error is your friend
Compilation error is your friend
if
if
if ,,
, when
when
when,,
, try
try
try etc. are expressions in kotlin
etc. are expressions in kotlin
etc. are expressions in kotlin
fun (a:Int,b:Int) =
a + if (b<5) a else -a
Even more type safety
Even more type safety
Even more type safety
sealed class Order(internal val sum: Int) {
open fun income(): Int = sum
fun cancelled() = Cancelled(this)
}
class Created(s: Int) : Order(s) {
override fun income(): Int = 0
fun pay() = Paid(this)
}
class Paid internal constructor(order: Created) : Order(order.sum) {
fun deliver() = Delivered(this)
}
class Delivered internal constructor(order: Paid) : Order(order.sum)
fun archive() = Archived(this)
}
class Cancelled internal constructor(order: Order) : Order(order.sum)
override fun income() = 0
}
class Archived internal constructor(order: Delivered) : Order(order.s
l d li t(
fun perfectDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
}
TOTALITARISM
TOTALITARISM
TOTALITARISM
Sounds like a wrong step. Let's see.
Sounds like a wrong step. Let's see.
Sounds like a wrong step. Let's see.
Say no to
Say no to
Say no to expected exceptions
expected exceptions
expected exceptions
fun parse(s:String) : Int = s.toInt()
fun String.asInt(): Either<ParseError, Int> =
if (this != null && this.matches(Regex("-?[0-9]+"))) {
this.toInt().right()
} else {
ParseError.WrongCharacters(this).left()
}

val z = "124".asInt()
Checked exceptions | 4xx =>
Checked exceptions | 4xx =>
Checked exceptions | 4xx => Either
Either
Either
Runtime exceptions | 5xx => Runtime
Runtime exceptions | 5xx => Runtime
Runtime exceptions | 5xx => Runtime
Exceptions
Exceptions
Exceptions
SIDE EFFECTS
SIDE EFFECTS
SIDE EFFECTS
SIDE EFFECTS
SIDE EFFECTS
SIDE EFFECTS
Functional programming is all about side
Functional programming is all about side
Functional programming is all about side
e ects
e ects
e ects
class Paid internal constructor(order: Created) : Order(order.sum) {
fun deliver() = Delivered(this).also {
println("delivered")
}
fun deliverFast() = Delivered(this).also {
println("delivered fast")
}
}
fun perfectDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
}
A surprise...
A surprise...
A surprise...
fun doubleDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
if (paid.income() > 20) {
paid.deliverFast()
}
}
fun main() = doubleDelivery()
//delivered
//delivered fast
SIDE EFFECTS
SIDE EFFECTS
SIDE EFFECTS
How not to have surprises (that often)
How not to have surprises (that often)
How not to have surprises (that often)
a fail
a fail
a fail
fun sayIt() = println("I said no side effects")
Too lazy to do side e ect
Too lazy to do side e ect
Too lazy to do side e ect
fun sayItLater() = { println("I said no side effects")}
Back to problem
Back to problem
Back to problem
fun crashDelivery() = run {
val created = Created(25)
val paid = created.pay()
paid.deliver()
if (paid.income() > 20) {
paid.deliverFast()
}
}
Naleśnik == pancake
Naleśnik == pancake
Naleśnik == pancake
class Naleśnik<out A>(private val nadzienie: () -> A) {
fun <B> przepakuj(f: (A) -> B) =
Naleśnik { f(this.nadzienie()) }
fun <B> zawiń(f: (A) -> Naleśnik<B>): Naleśnik<B> =
Naleśnik { f(this.nadzienie()).nadzienie() }
fun zjedz(): A = nadzienie() //use with caution
}
sealed class Order(internal val sum: Int) {
open fun income(): Int = sum
fun cancelled() = Naleśnik { Cancelled(this) }
}
class Created(s: Int) : Order(s) {
override fun income(): Int = 0
fun pay() = Naleśnik { Paid(this) }
}
class Paid internal constructor(order: Created) : Order(order.sum) {
fun deliver(): Naleśnik<Delivered> = Naleśnik {
Delivered(this).also {
println("delivered")
}
}
fun deliverFast(): Naleśnik<Delivered> = Naleśnik {
Delivered(this).also {
println("delivered fast")
}
}
}
fun crashDelivery():Naleśnik<Delivered> = run {
val created = Created(25)
val paid = created.pay()
val delivered = paid.zawiń { it.deliver() }
paid.zawiń { if (it.income()> 20) it.deliverFast() else
}
fun main() {
crashDelivery().zjedz()
//delivered fast
}
Naleśnik - harder to do e ect accidentally
Naleśnik - harder to do e ect accidentally
Naleśnik - harder to do e ect accidentally
Naleśnik > Burrito
Naleśnik > Burrito
Naleśnik > Burrito
Naleśnik
Naleśnik
Naleśnik == IO (Monad)
== IO (Monad)
== IO (Monad)
IO <A>
IO <A>
IO <A> ~=
~=
~= Mono<A>
Mono<A>
Mono<A>
in
in
in arrow-fx
arrow-fx
arrow-fx
IO<A>
IO<A>
IO<A> ==
==
== suspend () -> A
suspend () -> A
suspend () -> A
FRAMEWORKS - ENTERPRISY
FRAMEWORKS - ENTERPRISY
FRAMEWORKS - ENTERPRISY
CODE
CODE
CODE
Transaction is a Monad
Transaction is a Monad
Transaction is a Monad
class Transaction<A>(private val action: (Connection) -> A) {
fun <B> map ( f: (A)->B) = Transaction { conn -> f(action(conn))}
fun <B> flatMap( f: (A)->Transaction<B>) =
Transaction { conn -> f(action(conn)).action(conn) }
fun runTransaction(conn:Connection): Either<Exception, A> = run {
val initialAC = conn.autoCommit
conn.autoCommit = false
try {
val res = action(conn)
conn.commit()
Either.right(res)
} catch (e: Exception) {
conn.rollback()
Either.left(e)
} finally {
conn.autoCommit = initialAC
}
}
}
GENERIC EFFECT
IO<R,E,A>
IO<R,E,A>
IO<R,E,A>
R - environment (dependencies)
E - error (not only exception)
A - result (business)
Scala ZIO
Scala ZIO
Scala ZIO
NEE
mutilated
mutilated
mutilated ZIO <R,E,A>
ZIO <R,E,A>
ZIO <R,E,A> + spring like aspects
+ spring like aspects
+ spring like aspects
description
description
description
Instead of writing:
Instead of writing:
Instead of writing:
class Hasiok {
@Resource
val jdbcConnection: Connection
@Transactional
@Secure
@Cacheable
@Retryable
fun f(p:P) {
//code
}
}
Write:
Write:
Write:
class Hasiok {
fun enterprisyFunction(x:Int) = Nee.pure(
secure + retryable + cache.of(x) + tx
) {jdbcConnection:Connection ->
//code using jdbcConnection
}
//declaration above means security is checked before retri
//and retrial is made before cache which happens before tr
}
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
HOW DO I PROTECT MY PURITY?
What about discipline?
What about discipline?
What about discipline?
If
If
If I wanted to be careful with
I wanted to be careful with
I wanted to be careful with every line I write I
every line I write I
every line I write I
would have chosen PHP
would have chosen PHP
would have chosen PHP
KURE-POTLIN
KURE-POTLIN
KURE-POTLIN
https://github.com/nee ect/kure-potlin
https://github.com/nee ect/kure-potlin
https://github.com/nee ect/kure-potlin
Plugin for
Plugin for
Plugin for detekt
detekt
detekt
Plugin for
Plugin for
Plugin for detekt
detekt
detekt
Rule Detects Properties
with defaults
Requires
i
LoopUsage use of for, while active: true
ReturnStatement use of return statement active: true
VariableUsage use of var active: true
ReturnUnit use of function returning Unit, Nothing,
Void
active: true
checkFunctionType:
true
:ballot_box_with_check:
ClassDe nition use of object-oriented class active: false
AbstractClassDe nition use of object-oriented abstract class active: false
ThrowExpression use of throw active: true
MutableCollections use of mutable collections active: true :ballot_box_with_check:
BranchStatement use of if or when as statement :white_check_mark:
MissingElse use of if statement without else
type resolution
PROJECT LINKS
PROJECT LINKS
PROJECT LINKS
example of pure todo list with arrow-fx and
example of pure todo list with arrow-fx and
example of pure todo list with arrow-fx and
ktor
ktor
ktor
springy e ects for kotlin
springy e ects for kotlin
springy e ects for kotlin
example ktor project with Nee ("todo list like")
example ktor project with Nee ("todo list like")
example ktor project with Nee ("todo list like")
https://github.com/nee ect/kure-potlin
https://github.com/nee ect/kure-potlin
https://github.com/nee ect/kure-potlin
https://github.com/jarekratajski/just_another_to
https://github.com/jarekratajski/just_another_to
https://github.com/jarekratajski/just_another_to
https://github.com/nee ect/nee
https://github.com/nee ect/nee
https://github.com/nee ect/nee
https://github.com/nee ect/kotlin-stones
https://github.com/nee ect/kotlin-stones
https://github.com/nee ect/kotlin-stones
https://demo.nee ect.dev
https://demo.nee ect.dev
https://demo.nee ect.dev
SUMMARY
SUMMARY
SUMMARY
FP is not a silver bullet, but it can help ->
FP is not a silver bullet, but it can help ->
FP is not a silver bullet, but it can help ->
composability.
composability.
composability.
The road is long and has multiple
The road is long and has multiple
The road is long and has multiple milestones
milestones
milestones
Each milestone is a
Each milestone is a
Each milestone is a potential profit
potential profit
potential profit
Kotlin is not Scala - but can be quite pure
Kotlin is not Scala - but can be quite pure
Kotlin is not Scala - but can be quite pure
Runtime magic vs Compiler magic
Runtime magic vs Compiler magic
Runtime magic vs Compiler magic

Contenu connexe

Tendances

Nik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactNik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReact
OdessaJS Conf
 
Java 8 Streams & Collectors : the Leuven edition
Java 8 Streams & Collectors : the Leuven editionJava 8 Streams & Collectors : the Leuven edition
Java 8 Streams & Collectors : the Leuven edition
José Paumard
 

Tendances (20)

Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
 
Google guava
Google guavaGoogle guava
Google guava
 
Kotlin Generation
Kotlin GenerationKotlin Generation
Kotlin Generation
 
Programming Java - Lection 04 - Generics and Lambdas - Lavrentyev Fedor
Programming Java - Lection 04 - Generics and Lambdas - Lavrentyev FedorProgramming Java - Lection 04 - Generics and Lambdas - Lavrentyev Fedor
Programming Java - Lection 04 - Generics and Lambdas - Lavrentyev Fedor
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
 
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
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinAsync code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
 
Google Guava
Google GuavaGoogle Guava
Google Guava
 
Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner code
 
Nik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactNik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReact
 
Why Learn Python?
Why Learn Python?Why Learn Python?
Why Learn Python?
 
Developing iOS apps with Swift
Developing iOS apps with SwiftDeveloping iOS apps with Swift
Developing iOS apps with Swift
 
Kotlin
KotlinKotlin
Kotlin
 
Google guava - almost everything you need to know
Google guava - almost everything you need to knowGoogle guava - almost everything you need to know
Google guava - almost everything you need to know
 
Kotlin standard
Kotlin standardKotlin standard
Kotlin standard
 
The Magic Of Elixir
The Magic Of ElixirThe Magic Of Elixir
The Magic Of Elixir
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. Streams
 
Java 8 Streams & Collectors : the Leuven edition
Java 8 Streams & Collectors : the Leuven editionJava 8 Streams & Collectors : the Leuven edition
Java 8 Streams & Collectors : the Leuven edition
 
Into Clojure
Into ClojureInto Clojure
Into Clojure
 

Similaire à Pure kotlin

Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요
Chang W. Doh
 
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
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
HamletDRC
 
public class Person { private String name; private int age;.pdf
public class Person { private String name; private int age;.pdfpublic class Person { private String name; private int age;.pdf
public class Person { private String name; private int age;.pdf
arjuncp10
 
Scala - fra newbie til ninja på en time
Scala - fra newbie til ninja på en timeScala - fra newbie til ninja på en time
Scala - fra newbie til ninja på en time
karianneberg
 

Similaire à Pure kotlin (20)

Pure Kotlin Devoxx PL 2021
Pure Kotlin Devoxx PL 2021Pure Kotlin Devoxx PL 2021
Pure Kotlin Devoxx PL 2021
 
Hey Kotlin, How it works?
Hey Kotlin, How it works?Hey Kotlin, How it works?
Hey Kotlin, How it works?
 
No excuses, switch to kotlin
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlin
 
Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요
 
Features of Kotlin I find exciting
Features of Kotlin I find excitingFeatures of Kotlin I find exciting
Features of Kotlin I find exciting
 
Madrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovyMadrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovy
 
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
 
Java: Nie popełniaj tych błędów!
Java: Nie popełniaj tych błędów!Java: Nie popełniaj tych błędów!
Java: Nie popełniaj tych błędów!
 
Wykorzystanie języka Kotlin do aplikacji na platformie Android
Wykorzystanie języka Kotlin do aplikacji na platformie AndroidWykorzystanie języka Kotlin do aplikacji na platformie Android
Wykorzystanie języka Kotlin do aplikacji na platformie Android
 
Greach 2015 AST – Groovy Transformers: More than meets the eye!
Greach 2015   AST – Groovy Transformers: More than meets the eye!Greach 2015   AST – Groovy Transformers: More than meets the eye!
Greach 2015 AST – Groovy Transformers: More than meets the eye!
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
 
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
 
First few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesFirst few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examples
 
public class Person { private String name; private int age;.pdf
public class Person { private String name; private int age;.pdfpublic class Person { private String name; private int age;.pdf
public class Person { private String name; private int age;.pdf
 
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
 
Kotlin Overview (PT-BR)
Kotlin Overview (PT-BR)Kotlin Overview (PT-BR)
Kotlin Overview (PT-BR)
 
No excuses, switch to kotlin
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlin
 
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
 
Kotlin : Happy Development
Kotlin : Happy DevelopmentKotlin : Happy Development
Kotlin : Happy Development
 
Scala - fra newbie til ninja på en time
Scala - fra newbie til ninja på en timeScala - fra newbie til ninja på en time
Scala - fra newbie til ninja på en time
 

Plus de Jarek Ratajski

Lambda core
Lambda coreLambda core
Lambda core
Jarek Ratajski
 

Plus de Jarek Ratajski (15)

respect-estimates.pdf
respect-estimates.pdfrespect-estimates.pdf
respect-estimates.pdf
 
Lambda hardcore
Lambda hardcoreLambda hardcore
Lambda hardcore
 
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
 

Dernier

Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Dernier (20)

AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 

Pure kotlin

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