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

Ruby Function Composition

Ruby Function Composition

Ruby can elegantly blend both Functional Programming and Object Oriented design patterns together with minimal effort. In this talk, I'll combine both of these design patterns by briefly walking you through the fundamentals of functional composition, appling monads, and finally wrapping all of this up in a nice transactional pipeline object composed of multiple -- and fault tolerant -- operations for building more robust architectures. You'll learn a lot and walk away with new patterns to apply to your own code base.

Brooke Kuhlmann

February 13, 2023
Tweet

More Decks by Brooke Kuhlmann

Other Decks in Programming

Transcript

  1. Ruby Function Composition
    Presented by Brooke Kuhlmann
    g(f(x))
    f(x)
    x
    A B C
    f g

    View Slide

  2. Overview

    View Slide

  3. Ruby
    Overview
    Fundamentals

    View Slide

  4. Dry Monads
    Ruby
    Overview
    Fundamentals
    Railway Pattern

    View Slide

  5. Transactable
    Dry Monads
    Ruby
    Overview
    Fundamentals
    Railway Pattern
    Fault tolerent pipelines

    View Slide

  6. What?

    View Slide

  7. https://en.wikipedia.org/wiki/Function_composition_(computer_science)
    What

    View Slide

  8. https://en.wikipedia.org/wiki/Function_composition_(computer_science)
    What
    "[F]unction composition is an act or mechanism to combine simple
    functions to build more complicated ones. Like the usual
    composition of functions in mathematics, the result of each
    function is passed as the argument of the next, and the result of
    the last one is the result of the whole."
    -- Wikipedia

    View Slide

  9. https://www.alchemists.io/articles/ruby_function_composition
    What

    View Slide

  10. https://www.alchemists.io/articles/ruby_function_composition
    What

    View Slide

  11. https://www.alchemists.io/articles/ruby_function_composition
    What

    View Slide

  12. https://www.alchemists.io/articles/ruby_function_composition
    What

    View Slide

  13. https://www.alchemists.io/articles/ruby_function_composition
    What
    1

    View Slide

  14. https://www.alchemists.io/articles/ruby_function_composition
    What
    1
    2

    View Slide

  15. https://www.alchemists.io/articles/ruby_function_composition
    What
    1
    2 3

    View Slide

  16. https://www.alchemists.io/articles/ruby_function_composition
    What

    View Slide

  17. https://www.alchemists.io/articles/ruby_function_composition
    What
    (5 + 3) * 3 = 24

    View Slide

  18. History

    View Slide

  19. History
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  20. History
    Ruby 2.6.0
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  21. History
    Ruby 2.6.0
    Methods: #>> #<<
    https://www.alchemists.io/articles/ruby_function_composition
    (forward composition) (backward composition)

    View Slide

  22. History
    Ruby 2.6.0
    Methods:
    Proc Method
    #>> #<<
    Objects:
    https://www.alchemists.io/articles/ruby_function_composition
    (forward composition) (backward composition)

    View Slide

  23. Fundamentals

    View Slide

  24. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  25. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    Procs Lambdas Methods Classes

    View Slide

  26. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  27. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m m m m m
    m
    m m m m m m m
    3|
    | | | | | | | | | |
    Procs

    View Slide

  28. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m m m m m
    m
    m m m m m m m
    3|
    | | | | | | | | | |
    Procs

    View Slide

  29. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m m m m m
    m
    m m m m m m m
    3|
    | | | | | | | | | |
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # #
    Procs

    View Slide

  30. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m m m m m
    m
    m m m m m m m
    3|
    | | | | | | | | | |
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # #
    m
    m m m m m m m m m m m m m m m m m
    # #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    Procs

    View Slide

  31. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m m m m m
    m
    m m m m m m m
    3|
    | | | | | | | | | |
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # #
    m
    m m m m m m m m m m m m m m m m m
    # #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    m
    m m m m m m m m m m m m m m
    3 #
    #
    Procs

    View Slide

  32. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    multiplier = proc { |number, by = 3| number * by }
    multiplier.class # Proc
    multiplier.inspect # #
    multiplier.call 3 # 9
    multiplier.call 3, 10 # 30
    Procs

    View Slide

  33. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  34. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m
    m
    m m m m m m m
    3
    Lam
    bdas

    View Slide

  35. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m
    m
    m m m m m m m
    3
    Lam
    bdas

    View Slide

  36. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m
    m
    m m m m m m m
    3
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # #
    Lam
    bdas

    View Slide

  37. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m
    m
    m m m m m m m
    3
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    Lam
    bdas

    View Slide

  38. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m
    m
    m m m m m m m
    3
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    Lam
    bdas

    View Slide

  39. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    m
    m m m m m m m m m m m m m m
    m
    m m m m m m m
    3
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    m
    m m m m m m m m m m m m m m
    3 #
    #
    Lam
    bdas

    View Slide

  40. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    multiplier = -> number, by = 3 { number * by }
    multiplier.class # Proc
    multiplier.inspect # "#"
    multiplier.call 3 # 9
    multiplier.call 3, 10 # 30
    Lam
    bdas

    View Slide

  41. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  42. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    M
    ethods

    View Slide

  43. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    M
    ethods

    View Slide

  44. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    M
    ethods

    View Slide

  45. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    M
    ethods

    View Slide

  46. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    M
    ethods

    View Slide

  47. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # #
    M
    ethods

    View Slide

  48. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    M
    ethods

    View Slide

  49. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    M
    ethods

    View Slide

  50. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    m
    m m m m m m m m m m m m m m
    3 #
    #
    M
    ethods

    View Slide

  51. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    m
    m m m m m m m m m m m m m m
    3 #
    #
    m
    m m m m m m m m m m m m m m
    3, 1
    1
    #
    # #
    M
    ethods

    View Slide

  52. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    m
    m m m m m m m m m m m m m m
    3 #
    #
    m
    m m m m m m m m m m m m m m
    3, 1
    1
    #
    # #
    f
    f f f f f f f f f f f f f f f f f f f f f f f f f f
    M
    ethods

    View Slide

  53. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    C
    C C C C C C C C C C C C C C C C C C C C
    d
    d d d d d d
    .m
    m m m m m m m
    (
    ( ( ( ( ( ( ( ( ( (
    3)
    ) ) ) ) ) ) ) ) ) ) )
    m
    m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m
    m
    m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    m
    m m m m m m m m m m m m m m
    3 #
    #
    m
    m m m m m m m m m m m m m m
    3, 1
    1
    #
    # #
    f
    f f f f f f f f f f f f f f f f f f f f f f f f f f
    f
    f f f f f f f f
    c
    c c c c
    #
    # # # #
    M
    ethods

    View Slide

  54. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    Calculate = Module.new { def self.multiply(number, by = 3) = number * by }
    multiplier = Calculate.method :multiply
    multiplier.class # Method
    multiplier.inspect # "#"
    multiplier.call 3 # 9
    multiplier.call 3, 10 # 30
    function = multiplier.to_proc
    function.class # Proc
    function.inspect # #
    M
    ethods

    View Slide

  55. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    Calculate = Module.new { def self.multiply(number, by = 3) = number * by }
    multiplier = Calculate.method :multiply
    multiplier.class # Method
    multiplier.inspect # "#"
    multiplier.call 3 # 9
    multiplier.call 3, 10 # 30
    function = multiplier.to_proc
    function.class # Proc
    function.inspect # #
    M
    ethods

    View Slide

  56. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  57. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    c
    c c c c
    d
    d d
    3
    @
    @ @
    e
    e e
    d
    d d
    c
    c c c
    (
    ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (
    p
    p p p p p p
    e
    e e
    C
    lasses

    View Slide

  58. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    c
    c c c c
    d
    d d
    3
    @
    @ @
    e
    e e
    d
    d d
    c
    c c c
    (
    ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (
    p
    p p p p p p
    e
    e e
    C
    lasses

    View Slide

  59. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    c
    c c c c
    d
    d d
    3
    @
    @ @
    e
    e e
    d
    d d
    c
    c c c
    (
    ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (
    p
    p p p p p p
    e
    e e
    C
    lasses

    View Slide

  60. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    c
    c c c c
    d
    d d
    3
    @
    @ @
    e
    e e
    d
    d d
    c
    c c c
    (
    ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (
    p
    p p p p p p
    e
    e e
    m
    m m m m m m m m m m m m m m m m m m m m m m m m
    C
    lasses

    View Slide

  61. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    c
    c c c c
    d
    d d
    3
    @
    @ @
    e
    e e
    d
    d d
    c
    c c c
    (
    ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (
    p
    p p p p p p
    e
    e e
    m
    m m m m m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # # # # # #
    C
    lasses

    View Slide

  62. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    c
    c c c c
    d
    d d
    3
    @
    @ @
    e
    e e
    d
    d d
    c
    c c c
    (
    ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (
    p
    p p p p p p
    e
    e e
    m
    m m m m m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # # # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    C
    lasses

    View Slide

  63. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    c
    c c c c
    d
    d d
    3
    @
    @ @
    e
    e e
    d
    d d
    c
    c c c
    (
    ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (
    p
    p p p p p p
    e
    e e
    m
    m m m m m m m m m m m m m m m m m m m m m m m m
    m
    m m m m m m m m m m
    c
    c c c c
    #
    # # # # # # # # # #
    m
    m m m m m m m m m m m m m m m m m
    #
    #
    #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    m
    m m m m m m m m m m m m m m
    3 #
    #
    C
    lasses

    View Slide

  64. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    class Multiplier
    def initialize by = 3
    @by = by
    end
    def call(number) = number * by
    private
    attr_reader :by
    end
    multiplier = Multiplier.new
    multiplier.class # Multiplier
    multiplier.inspect # "#"
    multiplier.call 3 # 9
    Multiplier.new(10).call 3 # 30
    C
    lasses

    View Slide

  65. Fundamentals
    https://www.alchemists.io/articles/ruby_function_composition
    class Multiplier
    def initialize by = 3
    @by = by
    end
    def call(number) = number * by
    private
    attr_reader :by
    end
    multiplier = Multiplier.new
    multiplier.class # Multiplier
    multiplier.inspect # "#"
    multiplier.call 3 # 9
    Multiplier.new(10).call 3 # 30
    C
    lasses

    View Slide

  66. View Slide

  67. Composition

    View Slide

  68. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    Procs Lambdas Methods Classes
    >> >> >>

    View Slide

  69. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    Procs Lambdas Methods Classes
    >> >> >>

    View Slide

  70. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    Procs
    Lambdas Methods
    Classes
    >> >> >>

    View Slide

  71. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    Procs
    Lambdas
    Methods Classes
    >> >> >>

    View Slide

  72. Composition
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  73. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    © Wallpaper Cave
    Some assembly required.

    View Slide

  74. Composition
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  75. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    module Composable
    def >>(other) = method(:call) >> other
    def <<(other) = method(:call) << other
    def call = fail NotImplementedError, "`#{self.class.name}##{__method__}` must be implemented."
    end

    View Slide

  76. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    module Composable
    def >>(other) = method(:call) >> other
    def <<(other) = method(:call) << other
    def call = fail NotImplementedError, "`#{self.class.name}##{__method__}` must be implemented."
    end

    View Slide

  77. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    module Composable
    def >>(other) = method(:call) >> other
    def <<(other) = method(:call) << other
    def call = fail NotImplementedError, "`#{self.class.name}##{__method__}` must be implemented."
    end
    Transactable

    View Slide

  78. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    Class

    View Slide

  79. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    class Divider
    include Composable
    def initialize by = 3
    @by = by
    end
    def call(number) = number / by
    private
    attr_reader :by
    end
    Class

    View Slide

  80. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    class Divider
    include Composable
    def initialize by = 3
    @by = by
    end
    def call(number) = number / by
    private
    attr_reader :by
    end
    Class

    View Slide

  81. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    Method

    View Slide

  82. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    module Calculate
    def self.multiply(number, by = 3) = number * by
    end
    Method

    View Slide

  83. Composition
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  84. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    adder = proc { |number, by = 3| number + by }
    subtracter = -> number, by = 3 { number - by }
    divider = Divider.new
    multiplier = Calculate.method :multiply

    View Slide

  85. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    adder = proc { |number, by = 3| number + by }
    subtracter = -> number, by = 3 { number - by }
    divider = Divider.new
    multiplier = Calculate.method :multiply
    Proc

    View Slide

  86. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    adder = proc { |number, by = 3| number + by }
    subtracter = -> number, by = 3 { number - by }
    divider = Divider.new
    multiplier = Calculate.method :multiply
    Proc
    Lambda

    View Slide

  87. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    adder = proc { |number, by = 3| number + by }
    subtracter = -> number, by = 3 { number - by }
    divider = Divider.new
    multiplier = Calculate.method :multiply
    Proc
    Lambda
    Class

    View Slide

  88. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    adder = proc { |number, by = 3| number + by }
    subtracter = -> number, by = 3 { number - by }
    divider = Divider.new
    multiplier = Calculate.method :multiply
    Proc
    Lambda
    Class
    Method

    View Slide

  89. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    adder = proc { |number, by = 3| number + by }
    subtracter = -> number, by = 3 { number - by }
    divider = Divider.new
    multiplier = Calculate.method :multiply
    Proc
    Lambda
    Class
    Method
    Composable

    View Slide

  90. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    multiplier


    (method)
    subtractor


    (lambda)
    adder


    (proc)
    divider


    (class)
    >> >> >>

    View Slide

  91. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    multiplier


    (method)
    subtractor


    (lambda)
    adder


    (proc)
    divider


    (class)
    >> >> >>

    View Slide

  92. Composition
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  93. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39

    View Slide

  94. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    Forward composition

    View Slide

  95. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    Forward composition
    Backward composition

    View Slide

  96. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39

    View Slide

  97. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39

    View Slide

  98. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    (10 + 3) * 3 = 39

    View Slide

  99. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    (10 + 3) * 3 = 39
    📖

    View Slide

  100. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    (10 + 3) * 3 = 39
    📖
    1

    View Slide

  101. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    (10 + 3) * 3 = 39
    📖
    1

    View Slide

  102. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    (10 + 3) * 3 = 39
    📖
    1

    View Slide

  103. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    (10 + 3) * 3 = 39
    📖
    1
    2

    View Slide

  104. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39
    (10 + 3) * 3 = 39
    📖
    1
    2

    View Slide

  105. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39

    View Slide

  106. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (multiplier << adder).call 10 # 39

    View Slide

  107. Composition
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  108. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier >> subtracter >> divider).call 10 # 12
    (divider << subtracter << multiplier << adder).call 10 # 12

    View Slide

  109. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier >> subtracter >> divider).call 10 # 12
    (divider << subtracter << multiplier << adder).call 10 # 12
    (((10 + 3) * 3) - 3) / 3 = 12

    View Slide

  110. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier >> subtracter >> divider).call 10 # 12
    (divider << subtracter << multiplier << adder).call 10 # 12
    (((10 + 3) * 3) - 3) / 3 = 12

    View Slide

  111. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier >> subtracter >> divider).call 10 # 12
    (divider << subtracter << multiplier << adder).call 10 # 12
    (((10 + 3) * 3) - 3) / 3 = 12

    View Slide

  112. Composition
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  113. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    a
    a a a
    a
    a a a a a a a a a a a a
    a
    a a a a a a a a a a a a a a a a

    View Slide

  114. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    a
    a a a
    a
    a a a a a a a a a a a a
    a
    a a a a a a a a a a a a a a a a
    s
    s s s s s s s s s s s s s s s s s s s
    s
    s s s s s s s s s s s s s s s s s s

    View Slide

  115. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    a
    a a a
    a
    a a a a a a a a a a a a
    a
    a a a a a a a a a a a a a a a a
    s
    s s s s s s s s s s s s s s s s s s s
    s
    s s s s s s s s s s s s s s s s s s
    a
    a a a a a a a a a a a a a a a a a
    a
    a a a
    a
    a a a a a a a a a a
    a
    a a a
    a
    a a a a a a a a a a a a a a a a a a
    a
    a a a
    a
    a a a a a a a a a

    View Slide

  116. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    add_and_multiply = adder >> multiplier
    subtract_and_divide = subtracter >> divider
    add_multiply_subtract_and_divide = add_and_multiply >> subtract_and_divide
    add_multiply_subtract_and_divide.call 10 # 12

    View Slide

  117. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    add_and_multiply = adder >> multiplier
    subtract_and_divide = subtracter >> divider
    add_multiply_subtract_and_divide = add_and_multiply >> subtract_and_divide
    add_multiply_subtract_and_divide.call 10 # 12
    (((10 + 3) * 3) - 3) / 3 = 12

    View Slide

  118. Composition
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  119. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> multiplier).call 10 # 39
    (adder << multiplier).call 10 # 33
    Order of operations matters!

    View Slide

  120. Composition
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  121. Composition
    https://www.alchemists.io/articles/ruby_function_composition
    (adder >> Divider.new(0) >> multiplier).call 10 # ZeroDivisionError: divided by 0
    Any error will halt the operation.

    View Slide

  122. A Better Way?

    View Slide

  123. https://www.alchemists.io/projects/transactable

    View Slide

  124. https://www.alchemists.io/projects/transactable
    Transactable

    View Slide

  125. https://www.alchemists.io/projects/transactable
    Transactable
    Dry Monads
    Composition

    View Slide

  126. https://www.alchemists.io/projects/transactable
    Transactable
    Dry Monads
    Composition

    View Slide

  127. https://www.alchemists.io/projects/transactable
    Pipeline
    (Railway Pattern)

    View Slide

  128. https://www.alchemists.io/projects/transactable

    Pipeline
    (Railway Pattern)

    View Slide

  129. https://www.alchemists.io/projects/transactable

    Pipeline
    (Railway Pattern)

    View Slide

  130. https://www.alchemists.io/projects/transactable


    Pipeline
    (Railway Pattern)

    View Slide

  131. https://www.alchemists.io/projects/transactable


    Pipeline
    (Railway Pattern)

    View Slide

  132. https://www.alchemists.io/projects/transactable



    Pipeline
    (Railway Pattern)

    View Slide

  133. https://www.alchemists.io/projects/transactable




    Pipeline
    (Railway Pattern)

    View Slide

  134. https://www.alchemists.io/projects/transactable




    Success
    Success
    Success
    Pipeline
    (Railway Pattern)

    View Slide

  135. https://www.alchemists.io/projects/transactable




    Success
    Success
    Success
    Failure
    Failure
    Failure
    Pipeline
    (Railway Pattern)

    View Slide

  136. https://www.alchemists.io/projects/transactable




    Success
    Success
    Success
    Failure
    Failure
    Failure
    Pipeline
    No Exceptions!
    (Railway Pattern)

    View Slide

  137. https://kurzgesagt.org

    View Slide

  138. Kurzgesagt
    https://kurzgesagt.org

    View Slide

  139. Kurzgesagt
    (in a nutshell)
    https://kurzgesagt.org

    View Slide

  140. https://dry-rb.org/gems/dry-monads

    View Slide

  141. Dry Monads
    https://dry-rb.org/gems/dry-monads

    View Slide

  142. Dry Monads
    https://dry-rb.org/gems/dry-monads

    View Slide

  143. Dry Monads
    https://dry-rb.org/gems/dry-monads
    ✅ ❌

    View Slide

  144. Dry Monads
    https://dry-rb.org/gems/dry-monads
    Success
    ✅ ❌

    View Slide

  145. Dry Monads
    https://dry-rb.org/gems/dry-monads
    Success Failure
    ✅ ❌

    View Slide

  146. Dry Monads
    https://dry-rb.org/gems/dry-monads
    Success Failure
    ✅ ❌

    View Slide

  147. Dry Monads
    https://dry-rb.org/gems/dry-monads
    Success Failure
    ✅ ❌
    Ok

    View Slide

  148. Dry Monads
    https://dry-rb.org/gems/dry-monads
    Success Failure
    ✅ ❌
    Ok Err

    View Slide

  149. Dry Monads
    https://dry-rb.org/gems/dry-monads
    Success Failure
    ✅ ❌
    Ok Err
    Union Composite

    View Slide

  150. A Quick Script
    📝

    View Slide

  151. A Quick Script
    📝
    🔎

    View Slide

  152. Transactable
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  153. Transactable
    require "bundler/inline"
    gemfile true do
    source "https://rubygems.org"
    gem "amazing_print"
    gem "debug"
    gem "http"
    gem "dry-monads"
    gem "transactable"
    end
    Install
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  154. Transactable
    require "bundler/inline"
    gemfile true do
    source "https://rubygems.org"
    gem "amazing_print"
    gem "debug"
    gem "http"
    gem "dry-monads"
    gem "transactable"
    end
    Install
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  155. Transactable
    require "bundler/inline"
    gemfile true do
    source "https://rubygems.org"
    gem "amazing_print"
    gem "debug"
    gem "http"
    gem "dry-monads"
    gem "transactable"
    end
    Install
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  156. Transactable
    require "bundler/inline"
    gemfile true do
    source "https://rubygems.org"
    gem "amazing_print"
    gem "debug"
    gem "http"
    gem "dry-monads"
    gem "transactable"
    end
    Install
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  157. Transactable
    require "bundler/inline"
    gemfile true do
    source "https://rubygems.org"
    gem "amazing_print"
    gem "debug"
    gem "http"
    gem "dry-monads"
    gem "transactable"
    end
    Install
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  158. Transactable
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  159. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  160. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  161. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  162. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  163. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  164. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  165. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  166. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  167. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition
    Domain Speci
    fi
    c Language (DSL)

    View Slide

  168. Transactable
    class Pinger
    include Transactable
    def initialize client: HTTP
    @client = client
    end
    def call url
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    end
    end
    Im
    plem
    entation
    https://www.alchemists.io/articles/ruby_function_composition
    Domain Speci
    fi
    c Language (DSL)

    View Slide

  169. Transactable
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  170. Transactable
    class Pinger
    include Transactable
    # ...
    private
    attr_reader :client
    def get result
    result.fmap { |url| client.timeout(1).get url }
    rescue HTTP::TimeoutError => error
    Failure error.message
    end
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  171. Transactable
    class Pinger
    include Transactable
    # ...
    private
    attr_reader :client
    def get result
    result.fmap { |url| client.timeout(1).get url }
    rescue HTTP::TimeoutError => error
    Failure error.message
    end
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition
    🎗 method(:get)

    View Slide

  172. Transactable
    class Pinger
    include Transactable
    # ...
    private
    attr_reader :client
    def get result
    result.fmap { |url| client.timeout(1).get url }
    rescue HTTP::TimeoutError => error
    Failure error.message
    end
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition
    Monad

    View Slide

  173. Transactable
    class Pinger
    include Transactable
    # ...
    private
    attr_reader :client
    def get result
    result.fmap { |url| client.timeout(1).get url }
    rescue HTTP::TimeoutError => error
    Failure error.message
    end
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  174. Transactable
    class Pinger
    include Transactable
    # ...
    private
    attr_reader :client
    def get result
    result.fmap { |url| client.timeout(1).get url }
    rescue HTTP::TimeoutError => error
    Failure error.message
    end
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition
    Function Map

    View Slide

  175. Transactable
    class Pinger
    include Transactable
    # ...
    private
    attr_reader :client
    def get result
    result.fmap { |url| client.timeout(1).get url }
    rescue HTTP::TimeoutError => error
    Failure error.message
    end
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  176. Transactable
    class Pinger
    include Transactable
    # ...
    private
    attr_reader :client
    def get result
    result.fmap { |url| client.timeout(1).get url }
    rescue HTTP::TimeoutError => error
    Failure error.message
    end
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  177. Transactable
    class Pinger
    include Transactable
    # ...
    private
    attr_reader :client
    def get result
    result.fmap { |url| client.timeout(1).get url }
    rescue HTTP::TimeoutError => error
    Failure error.message
    end
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  178. Transactable
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  179. Transactable
    class Pinger
    include Transactable
    # ...
    private
    # ...
    def report(result) = result.fmap { |status| status == 200 ? "Site is up!" : status }
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  180. Transactable
    class Pinger
    include Transactable
    # ...
    private
    # ...
    def report(result) = result.fmap { |status| status == 200 ? "Site is up!" : status }
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition
    🎗 method(:report)

    View Slide

  181. Transactable
    class Pinger
    include Transactable
    # ...
    private
    # ...
    def report(result) = result.fmap { |status| status == 200 ? "Site is up!" : status }
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition
    Monad

    View Slide

  182. Transactable
    class Pinger
    include Transactable
    # ...
    private
    # ...
    def report(result) = result.fmap { |status| status == 200 ? "Site is up!" : status }
    end
    Privates
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  183. Transactable
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  184. Transactable
    include Dry::Monads[:result]
    url = "https://xkcd.com"
    case Pinger.new.call(url)
    in Success(message) then puts "Success: #{message}"
    in Failure(error) then puts "Site is down or invalid. Reason: #{error}"
    end
    Execution
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  185. Transactable
    include Dry::Monads[:result]
    url = "https://xkcd.com"
    case Pinger.new.call(url)
    in Success(message) then puts "Success: #{message}"
    in Failure(error) then puts "Site is down or invalid. Reason: #{error}"
    end
    Execution
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  186. Transactable
    include Dry::Monads[:result]
    url = "https://xkcd.com"
    case Pinger.new.call(url)
    in Success(message) then puts "Success: #{message}"
    in Failure(error) then puts "Site is down or invalid. Reason: #{error}"
    end
    Execution
    https://www.alchemists.io/articles/ruby_function_composition
    Input

    View Slide

  187. Transactable
    include Dry::Monads[:result]
    url = "https://xkcd.com"
    case Pinger.new.call(url)
    in Success(message) then puts "Success: #{message}"
    in Failure(error) then puts "Site is down or invalid. Reason: #{error}"
    end
    Execution
    https://www.alchemists.io/articles/ruby_function_composition
    Transaction

    View Slide

  188. Transactable
    include Dry::Monads[:result]
    url = "https://xkcd.com"
    case Pinger.new.call(url)
    in Success(message) then puts "Success: #{message}"
    in Failure(error) then puts "Site is down or invalid. Reason: #{error}"
    end
    Execution
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  189. View Slide

  190. Output
    🔎

    View Slide

  191. Transactable
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  192. Transactable
    Checking: https://xkcd.com...
    Success: Site is up!
    Input: https://xkcd.com
    Success
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  193. Transactable
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  194. Transactable
    Checking: http://xkcd.com...
    Site is down or invalid. Reason: http://xkcd.com
    Input: http://xkcd.com
    Failure
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  195. Transactable
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  196. Transactable
    Checking: https://www.unknown.com...
    Site is down or invalid. Reason: Timed out after using the allocated 1 seconds.
    Input: https://www.unknown.com
    Failure
    https://www.alchemists.io/articles/ruby_function_composition

    View Slide

  197. Wait, Rewind

    View Slide

  198. Wait, Rewind

    View Slide

  199. Transactable
    https://www.alchemists.io/projects/transactable

    View Slide

  200. Transactable
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    https://www.alchemists.io/projects/transactable

    View Slide

  201. Transactable
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    https://www.alchemists.io/projects/transactable

    View Slide

  202. Transactable
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    https://www.alchemists.io/projects/transactable
    The URL (raw input).

    View Slide

  203. Transactable
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    https://www.alchemists.io/projects/transactable
    The URL (raw input).
    Print info to the console.

    View Slide

  204. Transactable
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    https://www.alchemists.io/projects/transactable
    The URL (raw input).
    Print info to the console.
    Check if the URL is secure.

    View Slide

  205. Transactable
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    https://www.alchemists.io/projects/transactable
    The URL (raw input).
    Print info to the console.
    Check if the URL is secure.
    Make the HTTP GET request.

    View Slide

  206. Transactable
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    https://www.alchemists.io/projects/transactable
    The URL (raw input).
    Print info to the console.
    Check if the URL is secure.
    Make the HTTP GET request.
    Ask the HTTP response for status.

    View Slide

  207. Transactable
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)
    https://www.alchemists.io/projects/transactable
    The URL (raw input).
    Print info to the console.
    Check if the URL is secure.
    Make the HTTP GET request.
    Ask the HTTP response for status.
    Report the HTTP status.

    View Slide

  208. Transactable
    https://www.alchemists.io/projects/transactable
    Pipe
    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)

    View Slide

  209. Transactable
    https://www.alchemists.io/projects/transactable
    Pipe
    method :get
    url
    tee
    check
    as
    method :report





    pipe url,
    tee(Kernel, :puts, "Checking: #{url}..."),
    check(/\Ahttps/, :match?),
    method(:get),
    as(:status),
    method(:report)

    View Slide

  210. Architecture
    https://www.alchemists.io/projects/transactable
    method :get
    url
    tee
    check
    as
    method :report





    View Slide

  211. Architecture
    https://www.alchemists.io/projects/transactable
    method :get
    url
    tee
    check
    as
    method :report





    Input

    View Slide

  212. Architecture
    https://www.alchemists.io/projects/transactable
    method :get
    url
    tee
    check
    as
    method :report





    Step
    Step
    Step
    Step
    Step

    View Slide

  213. Architecture
    https://www.alchemists.io/projects/transactable
    method :get
    url
    tee
    check
    as
    method :report





    Monad
    Monad
    Monad
    Monad
    Monad

    View Slide

  214. Architecture
    https://www.alchemists.io/projects/transactable
    method :get
    url
    tee
    check
    as
    method :report





    Pipe

    View Slide

  215. Architecture
    https://www.alchemists.io/projects/transactable
    method :get
    url
    tee
    check
    as
    method :report





    Pipe

    View Slide

  216. Architecture
    https://www.alchemists.io/projects/transactable
    method :get
    url
    tee
    check
    as
    method :report





    Pipe

    View Slide

  217. Architecture
    https://www.alchemists.io/projects/transactable
    method :get
    url
    tee
    check
    as
    method :report





    Pipe

    View Slide

  218. https://www.alchemists.io/projects/transactable

    View Slide

  219. https://www.alchemists.io/projects/transactable
    Transactable
    Dry Monads
    Composition

    View Slide

  220. Thanks

    View Slide

  221. 🙇
    Thanks

    View Slide

  222. Let's Connect!

    View Slide

  223. Let's Connect!
    https://www.alchemists.io
    @[email protected]
    🌎

    View Slide

  224. Let's Connect!
    https://www.alchemists.io
    @[email protected]
    🌎
    Write

    Speak
    🎓
    Develop
    Screencast
    🎥
    Consult
    👥

    View Slide

  225. Let's Connect!
    https://www.alchemists.io
    @[email protected]
    🌎
    Write

    Speak
    🎓
    Develop
    Screencast
    🎥
    Ruby
    Elm
    HTMX
    Hanami
    Dry RB
    ROM
    Git
    Terraform
    Consult
    👥

    View Slide