@ilaborie #Java #Kotlin #Scala #2 @ilaborie #Java #Kotlin - - PowerPoint PPT Presentation

ilaborie java kotlin scala 2 ilaborie java kotlin scala 3
SMART_READER_LITE
LIVE PREVIEW

@ilaborie #Java #Kotlin #Scala #2 @ilaborie #Java #Kotlin - - PowerPoint PPT Presentation

@ilaborie #Java #Kotlin #Scala #2 @ilaborie #Java #Kotlin #Scala #3 @ilaborie #Java #Kotlin #Scala #4 Langages fonctionnels @ilaborie #Java #Kotlin #Scala #5 Fooling around with alternating current (AC) is just a


slide-1
SLIDE 1
  • @ilaborie #Java #Kotlin #Scala
slide-2
SLIDE 2

slide-3
SLIDE 3

@ilaborie #Java #Kotlin #Scala

#2

slide-4
SLIDE 4
  • @ilaborie #Java #Kotlin #Scala

#3

slide-5
SLIDE 5

Langages fonctionnels

@ilaborie #Java #Kotlin #Scala

#4

slide-6
SLIDE 6

Fooling around with alternating current (AC) is just a waste of time. Nobody will use it, ever. There is no reason anyone would want a computer in their home. I predict the Internet will soon go spectacularly supernova and in 1996 catastrophically collapse.

@ilaborie #Java #Kotlin #Scala

“ “ “

#5

slide-7
SLIDE 7

On peut adopter donc un style de programmation fonctionnelle avec la plupart des langages. Les caractéristiques des langages peuvent rendre cela plus ou moins facile (voir obligatoire)

@ilaborie #Java #Kotlin #Scala

#6

slide-8
SLIDE 8

Il n'y a qu'un langage fonctionnel : le ƛ-calcul

@ilaborie #Java #Kotlin #Scala

#7

slide-9
SLIDE 9

@ilaborie #Java #Kotlin #Scala

#8

slide-10
SLIDE 10

Programation fonctionnelle Typage statique

@ilaborie #Java #Kotlin #Scala

#9

slide-11
SLIDE 11

Partie I

@ilaborie #Java #Kotlin #Scala

#10

slide-12
SLIDE 12

@ilaborie #Java #Kotlin #Scala

class Utils { public static String doSomething(String arg) { throw new RuntimeException("Not yet impletmented"); } public static Function<String, String> asValue = Utils::doSomething; public static Function<String, String> aLambda = (String s) -> { throw new RuntimeException("Not yet impletmented") }; }

#11

slide-13
SLIDE 13

@ilaborie #Java #Kotlin #Scala

package object apackage { def doSomething(arg: String): String = ??? val asValue: String String = doSomething val aLambda: String String = (s: String) ??? } fun doSomething(arg: String): String = TODO() val asValue: String String = doSomething val aLambda: String String = { s: String TODO() }

#12

slide-14
SLIDE 14

  • void

@ilaborie #Java #Kotlin #Scala

class Test{ int sum = 0; public void compute() { var arr = List.of(1, 2, 3, 4, 5); for (int i : arr) { sum += i; } System.out.println(sum); } }

#13

slide-15
SLIDE 15

@ilaborie #Java #Kotlin #Scala

int sum = List.of(1, 2, 3, 4, 5) .stream() Stream<Integer> .reduce(0, (acc, i) -> acc + i); System.out.println(sum); val sum = List(1, 2, 3, 4, 5) .foldLeft(0) { (acc, i) acc + i } or .sum println(sum) val sum = listOf(1, 2, 3, 4, 5) .fold(0) { acc, i acc + i } or .sum() println(sum)

#14

slide-16
SLIDE 16

@ilaborie #Java #Kotlin #Scala

IntPredicate isEven = n -> { if (n % 2 0) { return true; } else { return false; } }; List.of(1, 2, 3, 4, 5) .forEach(i -> System.out.println("" + i + " is event? " + isEven.apply(i)) );

#15

slide-17
SLIDE 17

@ilaborie #Java #Kotlin #Scala

IntFunction<Boolean> isEven = n -> (n % 2 0)? true : false; val isEven = (n: Int) if (n % 2 0) true else false val isEven = { n: Int if (n % 2 0) true else false }

#16

slide-18
SLIDE 18

The last thing you wanted any programmer to do is mess with internal state even if presented figuratively. Instead, the objects should be presented as sites of higher level behaviors more appropriate for use as dynamic components.

@ilaborie #Java #Kotlin #Scala

#17

slide-19
SLIDE 19

@ilaborie #Java #Kotlin #Scala

public class Point { private int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } public void translateX(int offset) { this.x += offset; } + Getters + Setters + equals & hashCode + toString }

#18

slide-20
SLIDE 20

@ilaborie #Java #Kotlin #Scala

public class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } public Point translateX(int offset) { return new Point(this.x + offset, this.y); } + Getters + equals & hashCode + toString }

#19

slide-21
SLIDE 21

@ilaborie #Java #Kotlin #Scala

case class Point(x: Int, y: Int) { def translateX(offset: Int): Point = this.copy(x = x + offset) generated: Getters, equals & hashCode, toString, } data class Point(val x: Int, val y: Int) { fun translateX(offset: Int): Point = this.copy(x = x + offset) generated: Getters, equals & hashCode, toString, }

#20

slide-22
SLIDE 22

@ilaborie #Java #Kotlin #Scala

public class List<T> { private final T[] array; public List(T[] elements) { this.array = Arrays.copyOf(elements, elements.length); } public List<T> add(T element) { var newElts = Arrays.copyOf(this.array, this.array.length + 1); newElts[this.array.length] = element; return new List<>(newElts); } }

#21

slide-23
SLIDE 23

@ilaborie #Java #Kotlin #Scala

var digits = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); IntPredicate isEven = n -> (n % 2 0); List<Integer> evenDigits = digits.stream() .mapToInt(i -> i) .filter(isEven) .boxed() .collect(Collectors.toList()); UnaryOperator<IntPredicate> not = predicate -> i -> !predicate.test(i); IntPredicate isOdd = not.apply(isEven); isEven.negate() var oddDigits =

#22

slide-24
SLIDE 24

@ilaborie #Java #Kotlin #Scala

type Predicate[E] = E Boolean def not[E](p: Predicate[E]): Predicate[E] = e !p(e) val isEven: Predicate[Int] = n (n % 2 0) val isOdd = not(isEven) var evenDigits = digits.filter(isEven) val oddDigits = digits.filter(isOdd) typealias Predicate<E> = (E) Boolean fun <E> not(p: Predicate<E>): Predicate<E> = { e !p(e) } val isEven: Predicate<Int> = { n n % 2 0 } val isOdd = not(isEven) var evenDigits = digits.filter(isEven) val oddDigits = digits.filter(isOdd)

#23

slide-25
SLIDE 25
  • @ilaborie #Java #Kotlin #Scala

public static List<Event> notFunErrors1(List<Event> events, int size) { List<Event> result = new ArrayList<>(); for (int i = 0; i < result.size(); i) { Event event = events.get(i); if (event.isError()) { result.add(event); } if (result.size() size) { return result; } } return result; }

#24

slide-26
SLIDE 26
  • @ilaborie #Java #Kotlin #Scala

public static List<Event> notFunErrors2(List<Event> events, int size) { List<Event> result = new ArrayList<>(); for (Event event: events) { if (event.isError()) { result.add(event); } if (result.size() size) { return result; } } return result; }

#25

slide-27
SLIDE 27

@ilaborie #Java #Kotlin #Scala

public static List<Event> funErrors(List<Event> events, int size) { return events.stream() .filter(Event::isError) .limit(size) .collect(Collectors.toList()); }

#26

slide-28
SLIDE 28
  • @ilaborie #Java #Kotlin #Scala

def notFunErrors(events: List[Event], size: Int): List[Event] = { for { event events if event.isError } yield event }.take(size) def funErrors(events: List[Event], size: Int): List[Event] = events .filter(_.isError) .take(size)

#27

slide-29
SLIDE 29
  • @ilaborie #Java #Kotlin #Scala

fun notFunErrors(events: List<Event>, size: Int): List<Event> { val result = mutableListOf<Event>() for (event in events) { if (event.isError) { result.add(event) } if (result.size size) { return result } } return result } fun funErrors(events: List<Event>, size: Int): List<Event> = events .filter { it.isError } .take(size)

#28

slide-30
SLIDE 30

@ilaborie #Java #Kotlin #Scala

public static int factorialFor(int n) { int acc = 1; for (int i = 2; i n; i) { acc *= i; } return acc; } public static int factorialRec(int n) { return (n 1) ? 1 : n * factorialRec(n - 1); }

#29

slide-31
SLIDE 31

@ilaborie #Java #Kotlin #Scala

public static int factorialTailRec(int n) { return factorialTailRecAux(1, n); } private static int factorialTailRecAux(int acc, int n) { return (n 1) ? acc : factorialTailRecAux(acc * n, n - 1); } public static int factorialStream(int n) { return IntStream.rangeClosed(1, n) .reduce(1, (acc, i) -> acc * i); }

#30

slide-32
SLIDE 32

@ilaborie #Java #Kotlin #Scala

def factorialTailRec(n: Int): Int = { @tailrec def aux(acc: Int, n: Int): Int = if (n 1) acc else aux(acc * n, n - 1) aux(1, n) } tailrec fun factorialTailRec(n: Int): Int { fun aux(acc: Int, n: Int): Int = if (n 1) acc else aux(acc * n, n - 1) return aux(1, n) }

#31

slide-33
SLIDE 33

@ilaborie #Java #Kotlin #Scala

speakers.filter(speaker -> speaker.xp > 10 speaker.getLanguages().contains("Java")); speakers.filter(speaker -> speaker.xp > 10) is experimented is love Java .filter(speaker -> speaker.getLanguages().contains("Java")); Predicate<Speaker> isExperimented = speaker -> speaker.xp > 10; Predicate<Speaker> isLoveJS = speaker -> speaker.getLanguages().contains("Ja speakers.filter(isExperimented) .filter(isLoveJS); speakers.filter(isExperimented.and(isLoveJS));

#32

slide-34
SLIDE 34
  • @FunctionalInterface
  • Stream

Function#compose Function#andThen

  • java.util.function.*
  • final
  • tailrec
  • @ilaborie #Java #Kotlin #Scala

#33

slide-35
SLIDE 35
  • tailrec data

case

  • @ilaborie #Java #Kotlin #Scala

#34

slide-36
SLIDE 36

Partie II

@ilaborie #Java #Kotlin #Scala

#35

slide-37
SLIDE 37

@ilaborie #Java #Kotlin #Scala

#36

slide-38
SLIDE 38

@ilaborie #Java #Kotlin #Scala

#37

slide-39
SLIDE 39

Transformation d'une fonction de plusieurs arguments en une chaîne de fonctions d'un seul argument qui donnera le même résultat lorsqu'il est appelé en séquence avec les mêmes arguments.

f(x, y, z) = g(x)(y)(z) ⚠

@ilaborie #Java #Kotlin #Scala

#38

slide-40
SLIDE 40

@ilaborie #Java #Kotlin #Scala

IntBinaryOperator mult = (a, b) -> a * b; Curry IntFunction<IntFunction> curriedMult = b -> a -> a * b; Usage IntFunction identity = a -> mult.applyAsInt(a, 1); IntFunction dbl = curriedMult.apply(2);

#39

slide-41
SLIDE 41

type IntFun = (number) number; const stupidMemoizer = (fun: IntFun): IntFun { const cache: number[] = []; return (n: number) { const cached = cache[n]; if (typeof cached 'number') { return cached; } return (cache[n] = fun.call(null, n)); } }; const fibonacci: IntFun = stupidMemoizer(n { switch (n) { case 1 : return 1; case 2 : return 1; default: return fibonacci(n - 2) + fibonacci(n - 1); } }); console.log('fibonacci(15)', fibonacci(15));

slide-42
SLIDE 42

@ilaborie #Java #Kotlin #Scala

public static int fibonacci(int n) { switch (n) { case 1 return 1; case 2: return 1; default: return fibonacci(n - 2) + fibonacci(n - 1); } } public static IntUnaryOperator stupidMemoizer(IntUnaryOperator func) { Map<Integer, Integer> cache = new HashMap<>(); return n -> cache.computeIfAbsent(n, func::applyAsInt); } public static void main(String[] args) { var fibo = stupidMemoizer(Memo::fibonacci); System.out.println(fibo.applyAsInt(15)); }

#40

slide-43
SLIDE 43
  • @ilaborie #Java #Kotlin #Scala

#41

slide-44
SLIDE 44
  • @ilaborie #Java #Kotlin #Scala

type schoolPerson = Teacher | Director | Student(string);

#42

slide-45
SLIDE 45

@ilaborie #Java #Kotlin #Scala

let greeting = stranger switch (stranger) { | Teacher "Hey professor!" | Director "Hello director." | Student("Richard") "Still here Ricky?" | Student(anyOtherName) "Hey, " ++ anyOtherName ++ "." };

#43

slide-46
SLIDE 46

ifelseifelse instanceof

@ilaborie #Java #Kotlin #Scala

#44

slide-47
SLIDE 47

@ilaborie #Java #Kotlin #Scala

val greeting = stranger match { case Teacher "Hey professor!" case Director "Hey director." case Student("Richard") "Still here Ricky?" case Student(name) s"Hey, $name." } val greeting = when (stranger) { is Teacher "Hey professor!" is Director "Hey director." Student("Richard") "Still here Ricky?" is Student "Hey, ${stranger.name}." }

#45

slide-48
SLIDE 48

A monad is just a monoïd in the category of endofunctors, what's the problem?

  • @ilaborie #Java #Kotlin #Scala

#46

slide-49
SLIDE 49

Généralisation aux catégories de la notion de morphisme.

  • @ilaborie #Java #Kotlin #Scala

interface Functor<A> { Functor<B> map(mapper: Function<A, B>); avec associativité } interface EndoFunctor<A> { EndoFunctor<A> map(mapper: UnaryOperator<A>); }

#47

slide-50
SLIDE 50

C'est un magma associatif et unifère, c'est-à-dire un demi-groupe unifère.

  • @ilaborie #Java #Kotlin #Scala

interface SemiGroup { SemiGroup concat(SemiGroup other); this.concat(x.concat(y)) = this.concat(x).concat(y) } interface Monoid extends SemiGroup { static Monoid neutral = ???; monoid.concat(neutral) = monoid, neutral.concat(monoid) = monoid }

#48

slide-51
SLIDE 51

@ilaborie #Java #Kotlin #Scala

interface Monad<A> extends Functor<A> { Monad<B> flatMap(mapper: Function<A, Monad<B>>); }

#49

slide-52
SLIDE 52

J'ai toujours pas compris !

  • map

flatMap Option<V> Either<A,B> Try<S,E> Future<V>

@ilaborie #Java #Kotlin #Scala

#50

slide-53
SLIDE 53
  • map flatMap
  • @ilaborie #Java #Kotlin #Scala

#51

slide-54
SLIDE 54

Remaques sur la performance

@ilaborie #Java #Kotlin #Scala

#52

slide-55
SLIDE 55

@ilaborie #Java #Kotlin #Scala

#53

slide-56
SLIDE 56

Douter de toutes les mythes et légendes

@ilaborie #Java #Kotlin #Scala

#54

slide-57
SLIDE 57

tous les leviers sont bon, y compris le langage

@ilaborie #Java #Kotlin #Scala

#55

slide-58
SLIDE 58

Conclusion

@ilaborie #Java #Kotlin #Scala

#56

slide-59
SLIDE 59
  • java.util.function

java.util.stream

  • XXXFunction CompletableFuture

Collectors.toList

@ilaborie #Java #Kotlin #Scala

#57

slide-60
SLIDE 60

java.util.concurrent.Flow

@ilaborie #Java #Kotlin #Scala

#58

slide-61
SLIDE 61

@ilaborie #Java #Kotlin #Scala

#59

slide-62
SLIDE 62
  • @ilaborie #Java #Kotlin #Scala

#60

slide-63
SLIDE 63

@ilaborie #Java #Kotlin #Scala

#61

slide-64
SLIDE 64