Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Treasure.map(): Functional programming in JVM-based languages

Treasure.map(): Functional programming in JVM-based languages

A5503b91ff91d4f8041bcce9bd5ca5ee?s=128

Karin-Aleksandra Monoid

June 08, 2022
Tweet

More Decks by Karin-Aleksandra Monoid

Other Decks in Programming

Transcript

  1. 1 Treasure.Map(): Functional Programming in JVM-based languages Karin-Aleksandra Monoid GDSC

    KPI, 2022
  2. 2 • Senior Software Engineer at CircleCI • Background in

    Kotlin & Scala (both front and backend) • Living in Potsdam with two cats • GDE in Kotlin About
  3. 3 Why?

  4. 4 “Why can we tell people about internals of JVM

    and no one bats an eye but should I only add a word “monad” and everyone is too scared because it’s so difficult?” – Conclusions on the speaker dinner/Joker 2021 Motivation
  5. 5 Agenda Elements of functional programming Monads Error handling When

    to use?
  6. 6 Languages • Kotlin • Java • Scala • Clojure

    • Groovy
  7. 7 Elements of functional programming

  8. 8 What is functional programming? https://blog.knoldus.com/

  9. 9 Pure functions • Same input = same output •

    No “side-effects” • Not altering any global state
  10. 10 Immutability • Java: records, final, vavr • Kotlin: val,

    read-only collection interfaces, Arrow, kotlinx.collections.immutable • Scala: vals, scala.collection.* and scala.collection.immutable.* • Clojure: everything but def • Groovy: @Immutable meta-annotation, asImmutable()
  11. 11 True immutability vs reference immutability? Java: final List<Integer> list

    = Arrays.asList(1, 2, 3); We can’t reassign it like list = Arrays.asList(1, 2, 6); But can alter the list itself e.g. with set(0, 10) We can wrap with unmodifiableList or use List.of to begin with, but we don’t know by type whether provided list is mutable (ArrayList), semi-mutable (Arrays.asList) or unmodifiable. Also deep structures are not covered.
  12. 12 Collection immutability: Groovy See: Java (but there is .asImmutable())

  13. 13 Collection immutability: Scala scala.collection.* - you cannot modify but

    somebody else might be able to. scala.collection.immutable.* - nobody can modify collection itself scala.collection.mutable.* - you can modify this
  14. 14 Collection immutability: Kotlin Collection, List, etc - you cannot

    modify but somebody else might be able to. MutableCollection, MutableList, etc - you can modify this ImmutableList (from kotlinx.collections.immutable) - nobody can modify collection/list
  15. 15 Collection immutability: Clojure Everything is truly immutable

  16. 16 Map (🐸, 🐸, 🐸).map(🐸 -> 🦄) => (🦄, 🦄,

    🦄) Java items.stream().map(frog -> unicorn).toList() Groovy items.collect(frog -> unicorn) Kotlin items.map { frog -> unicorn } Scala items.map(frog => unicorn) Clojure (map (constantly unicorn) items)
  17. 17 Filter (🐸, 🐸, 🦄, 🦄, 🐸, 🦄).filter(🐸?) => (🐸,

    🐸, 🐸) Java items.stream().filter(Animal::isFrog).toList() Groovy items.findAll { it.isFrog() } Kotlin items.filter { it.isFrog() } Scala items.filter(isFrog(_)) Clojure (filter is-frog? items)
  18. 18 Fold (👩, 👩, 👧, 👦).fold(+) => 󰔮 Java items.stream().collect(collector)

    Groovy items.inject(acc, …) Kotlin items.fold(acc) {...} Scala tems.fold(acc)(...) Clojure (r/fold function acc items)
  19. 19 FlatMap (🟧, 🟨, 🟩, 🟦).flatMap(⬜ -> (🤍, ⚪)) =>

    (🧡, 🟠, 💛, 🟡, 💚, 🟢, 💙, 🔵) Java items.stream.flatMap(...).toList() Groovy items.collectMany(...) Kotlin items.flatMap {...} Scala items.flatMap(...) Clojure (mapcat transform items)
  20. 20 Monads

  21. 21 A monad A monad is just a monoid in

    a category of the endofunctors
  22. 22 Monads Do you know monads? Do you use a

    `List`? That’s a monad!
  23. 23 Monads in the simple terms A type: • An

    instance of which can be created • Which has flatMap() function
  24. 24 Monad comprehensions combined = for { a <- listA

    b <- listB } yield a * b Which is equal to combined = listA.flatMap(a => listB.flatMap(b => a * b))
  25. 25 Monad comprehensions combined = for { a <- optionA

    b <- optionB } yield a * b Which is equal to combined = optionA.flatMap(a => optionB.flatMap(b => a * b))
  26. 26 Error handling

  27. 27 if (somethingWrong) throw new SomeException(...) Java Exceptions

  28. 28 Java Exceptions - “Handling” in signature void testFun() throws

    SomeException
  29. 29 Java Exceptions - Handling with try try { testFun()

    } catch (SomeException e) { ... }
  30. 30 Java Exceptions IntStream.range(0, 10) .forEach(i -> testFun()) void testFun()

    throws SomeException
  31. 31 Java Exceptions IntStream.range(0, 10) .forEach(i -> testFun()) void testFun()

    throws SomeException
  32. 32 Java Exceptions IntStream.range(0, 10) .forEach(hideException(i -> testFun()));

  33. 33 Java Exceptions unhideSomeException(() -> IntStream.range(0, 10) .forEach( hideException(i ->

    testFun() )));
  34. 34 All other languages Checked exceptions are gone!

  35. 35 Demo K: (0 until 10).forEach { testFun() } S:

    (0 until 10).foreach { testFun() } C: (run test-fun (range 10)) G: (1..<3).each { testFun() }
  36. 36 How to handle problems: Groovy ¯\_(ツ)_/¯

  37. 37 How to handle problems: Kotlin, safer null fun String.toIntOrNull():

    Int?
  38. 38 How to handle problems: Kotlin, Result type runCatching {

    doSomething() }
  39. 39 How to handle problems: Kotlin, sealed types sealed class

    Result class SuccessfullyInvested : Result() class LostMoney : Result()
  40. 40 How to handle problems: Scala, Option Something or none

    def toIntOption: Option[Int] Some(5) or None
  41. 41 How to handle problems: Scala, Either val result: Either[DbError,

    User] = db.findUser(id) Left(UserNotFound) or Right(User(123))
  42. 42 How to handle problems: Scala, Either Either is also

    a monad val userSummary = for { user <- db.findUser(id) balance <- db.findUserBalance(user.bankId) } yield UserSummary(user, balance)
  43. 43 Either Kotlin+Arrow: Either<Failure, Success> Java+vavr: Either<Failure, Success>

  44. 44 How to handle problems: Clojure ¯\_(ツ)_/¯

  45. 45 How to handle problems: Clojure ¯\_(ツ)_/¯ REPL

  46. 46 Frameworks and libraries Java, Groovy: vavr Kotlin: Arrow Scala:

    Cats, zio Clojure: just continue using REPL
  47. 47 • You are using elements of FP already •

    Consider support of libraries • Consider team knowledge • Immutability may be slow-ish Conclusions