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

C'est qui Reason(ML) et qu'est ce qu'il fait là?

C'est qui Reason(ML) et qu'est ce qu'il fait là?

Maxime Thirouin

November 20, 2018
Tweet

More Decks by Maxime Thirouin

Other Decks in Technology

Transcript

  1. @MoOx
    C'est qui Reason(ML)
    et qu'est ce qu'il fait là?
    1

    View Slide

  2. @MoOx
    Do you need
    redux?
    2
    Previously in React Toulouse…

    View Slide

  3. @MoOx
    Redux

    is a predictable state container
    for JavaScript apps.
    3
    Previously in React Toulouse…

    View Slide

  4. @MoOx
    What redux does,
    ReasonReact and Elm do
    4
    Actions are types, reducers are functions,

    state is immutable, but at the language level
    Previously in React Toulouse…

    View Slide

  5. @MoOx
    “done in collaboration with the ReactJS team”
    5 https://reasonml.github.io/reason-react/blog/2017/09/01/reducers.html
    Previously in React Toulouse…

    View Slide

  6. @MoOx
    6
    JS

    View Slide

  7. @MoOx
    • Available everywhere
    • Easy to start
    • Multiparadigm
    7

    View Slide

  8. @MoOx
    • Super hard to master
    • Error prone
    • Hacky
    8

    View Slide

  9. @MoOx
    9
    let add = (a, b) => a + b;

    View Slide

  10. @MoOx
    10
    add(1, 1); // 2
    add(1, "1"); // "11"
    add(1, null); // 1
    add(1, undefined); // NaN

    View Slide

  11. @MoOx
    Dynamic typing
    + Automatic coercion
    11

    View Slide

  12. @MoOx
    12

    View Slide

  13. @MoOx

    13

    View Slide

  14. @MoOx
    • ESLint?
    • Flow?
    • TypeScript?
    14

    View Slide

  15. @MoOx
    15

    View Slide

  16. @MoOx
    Developers are humans
    16
    And we make mistakes

    View Slide

  17. @MoOx
    What about TESTS?
    17

    View Slide

  18. @MoOx
    We covers what we
    think about.
    18
    And we are developers. And we make mistakes

    View Slide

  19. @MoOx
    19

    View Slide

  20. @MoOx
    20

    View Slide

  21. @MoOx
    21
    1. A language
    2. A syntax
    3. A compiler
    4. An ecosystem

    View Slide

  22. @MoOx
    OCaml
    22

    %

    View Slide

  23. @MoOx
    • Has a great type system
    • Infers most types
    • Multiparadigm
    23

    View Slide

  24. @MoOx
    Syntax can be hard
    Tooling can be hard
    24

    View Slide

  25. @MoOx
    let rec map f = function
    [] -> []
    | a::l -> let r = f a in r :: map f l
    25

    View Slide

  26. @MoOx
    1. A language
    2. A syntax
    3. A compiler
    4. An ecosystem
    26

    View Slide

  27. @MoOx
    ~ES2015+
    27
    JS

    View Slide

  28. @MoOx
    28
    let add a b = a + b
    let add = (a, b) => a + b;
    ML
    RE

    View Slide

  29. @MoOx
    29
    1. A language
    2. A syntax
    3. A compiler
    4. An ecosystem

    View Slide

  30. @MoOx
    BuckleScript
    30

    View Slide

  31. @MoOx
    RE

    31
    JS

    View Slide

  32. @MoOx
    • Outputs clean and
    performant code
    • Makes interop easy
    32
    BUCKLESCRIPT

    View Slide

  33. @MoOx
    33
    1. A language
    2. A syntax
    3. A compiler
    4. An ecosystem

    View Slide

  34. @MoOx
    34
    npm

    View Slide

  35. @MoOx
    A bit of practice?
    35

    View Slide

  36. @MoOx
    1. Basics
    2. Modules
    3. Functions
    4. Variants
    5. Interop
    36

    View Slide

  37. @MoOx
    37
    BASICS
    1; /* int */
    1.0; /* float */
    "Hello"; /* string */
    'H'; /* char */
    true; /* bool */

    View Slide

  38. @MoOx
    38
    BASICS
    [1, 2, 3]; /* list(int) */
    [|1, 2, 3|]; /* array(int) */
    Some(x); /* option('a) */
    () /* unit */

    View Slide

  39. @MoOx
    39
    RECORDS
    let me = {
    name: "Matthias",
    age: 24,
    };
    let meLater = {
    ...me,
    age: 25,
    };
    type user = {
    name: string,
    age: int,
    };
    You declare the type of the record
    You can create records of this type
    You can create spread values to create a new
    record from a previous one

    View Slide

  40. @MoOx
    1. Basics
    2. Modules
    3. Functions
    4. Variants
    5. Interop
    40

    View Slide

  41. @MoOx
    41
    App.re
    MODULES
    Every file is a module
    and filenames are unique
    Welcome.re
    let sayHi = (name) => Js.log("Hi " ++ name ++ "!");
    Welcome.sayHi("people");
    Every top level binding is exported
    by default
    To open a module, just use its
    capitalised name

    View Slide

  42. @MoOx
    42
    MODULES
    module Talk {
    include Presentation;
    let slides = ["a", "b", "c"];
    let slidesWithIndex = slides
    ->Belt.List.mapWithIndex((index, item) => (index, item));
    };
    open OtherModule;
    Declare a module within a module
    Include modules
    like a static extends
    Make all module
    available in scope

    View Slide

  43. @MoOx
    1. Basics
    2. Modules
    3. Functions
    4. Variants
    5. Interop
    43

    View Slide

  44. @MoOx
    44
    FUNCTIONS
    let add = (a, b) => a + b;
    let addDoubles = (a, b) => {
    let doubleA = a * 2;
    let doubleB = b * 2;
    doubleA + doubleB;
    };
    Every function has its signature
    let add: (int, int) => int = ;
    Last expression is the
    returned value

    View Slide

  45. @MoOx
    45
    FUNCTIONS
    Pipe operator!
    Functions are auto curried
    That means that they return a function
    taking the rest of the arguments as long
    as you didn't pass all the required ones
    [1, 2, 3]
    ->Belt.List.keep(item => item mod 2 === 0)
    ->Belt.List.map(item => item * 2);

    View Slide

  46. @MoOx
    46
    FUNCTIONS
    let make = (
    ~rootPath="./",
    ~fileExtensions=["re", "js"],
    ~watch=false,
    ~onChange=?,
    ()
    ) => {
    /* ... */
    };
    Functions can have labelled arguments
    Their order at function application doesn't mater
    Optionals
    Default values
    Final non labelled argument
    When you have optional arguments, this tells
    the compiler «I have all the arguments there»

    View Slide

  47. @MoOx
    1. Basics
    2. Modules
    3. Functions
    4. Variants
    5. Interop
    47

    View Slide

  48. @MoOx
    48
    WHAT'S WRONG WITH THIS?
    type state = {
    isLoading: false,
    hasErrored: false,
    data: null,
    };

    View Slide

  49. @MoOx
    49
    IMPOSSIBLE STATES ARE ACTUALLY POSSIBLE
    isLoading hasErrored data
    FALSE FALSE NULL
    TRUE FALSE NULL
    FALSE TRUE NULL
    TRUE TRUE NULL
    FALSE FALSE DATA
    TRUE FALSE DATA
    FALSE TRUE DATA
    TRUE TRUE DATA
    NotAsked
    Loading
    Errored
    Loaded

    View Slide

  50. @MoOx
    50
    THE SOLUTION: VARIANTS
    type t('a) =
    | NotAsked
    | Loading
    | Loaded('a)
    | Errored;
    A variant type is a «OR» type
    A type can be parametrised
    aka Generics
    Every constructor can hold data
    like a container type

    View Slide

  51. @MoOx
    51
    THE SOLUTION: VARIANTS
    switch (resource) {
    | NotAsked => ""
    | Loading => "Loading ..."
    | Loaded(value) => "Loaded: " ++ value
    | Errored => "An error occurred"
    };
    You use pattern matching to extract values

    View Slide

  52. @MoOx
    52
    THE SOLUTION: VARIANTS
    switch (resource) {
    | NotAsked => ""
    | Loading => "Loading ..."
    | Loaded(value) => "Loaded: " ++ value
    };
    Warning 8: this pattern-matching is not exhaustive. Here is an
    example of a value that is not matched: Errored

    View Slide

  53. @MoOx
    53
    THERE'S NO NULL
    type option('a) =
    | Some('a)
    | None;
    switch (value) {
    | Some(value) => value
    | None => "Nothing to see"
    };
    Move null checks at compile time
    If it's maybe a value, you need to handle it explicitly

    View Slide

  54. @MoOx
    54
    1
    ARRAY VS LIST
    1 2 3
    1
    1 1
    2 1
    3 1

    View Slide

  55. @MoOx
    55
    LIST IS A VARIANT TYPE
    type list('a) =
    | Empty
    | Head('a, list('a));
    let list = Head(1, Head(2, Head(3, Empty)));

    View Slide

  56. @MoOx
    56
    LIST IS A VARIANT TYPE
    If there's nothing left
    Return empty
    Return a head with
    transformed item
    then transform the rest
    with a recursive call
    Recursive
    let rec map = (f, list) =>
    switch (list) {
    | Empty => Empty
    | Head(x, rest) => Head(f(x), map(f, rest))
    };

    View Slide

  57. @MoOx
    57
    LIST IS A VARIANT TYPE
    Reassigned
    Reassigned
    let foldLeft = (array, f, acc) => {
    let index = -1;
    while(++index < array.length) {
    acc = f(acc, array[index])
    };
    return acc
    };

    View Slide

  58. @MoOx
    58
    ACTUALLY IN JS
    // http://es5.github.io/#x15.4.4.21
    function foldLeft(arr, fn) {
    var array = new Object(arr),
    index = -1,
    length = array.length >>> 0,
    acc,
    hasInitialValue;
    if (Object.prototype.toString.call(fn) != "[object Function]") {
    throw new TypeError();
    }
    if (arguments.length > 1) {
    acc = arguments[1];
    } else {
    hasInitialValue = false;
    while (++index < length) {
    if (!(hasInitialValue = index in array)) {
    continue;
    }
    acc = array[index];
    break;
    }
    if (!hasInitialValue) {
    throw new TypeError();
    }
    }
    while (++index < length) {
    if (!(index in array)) continue;
    acc = fn.call(void 0, acc, array[index], index, array);
    }
    return acc;
    };

    View Slide

  59. @MoOx
    59
    ACTUALLY IN JS: DYNAMIC TYPING
    // http://es5.github.io/#x15.4.4.21
    function foldLeft(arr, fn) {
    var array = new Object(arr),
    index = -1,
    length = array.length >>> 0,
    acc,
    hasInitialValue;
    if (Object.prototype.toString.call(fn) != "[object Function]") {
    throw new TypeError();
    }
    if (arguments.length > 1) {
    acc = arguments[1];
    } else {
    hasInitialValue = false;
    while (++index < length) {
    if (!(hasInitialValue = index in array)) {
    continue;
    }
    acc = array[index];
    break;
    }
    if (!hasInitialValue) {
    throw new TypeError();
    }
    }
    while (++index < length) {
    if (!(index in array)) continue;
    acc = fn.call(void 0, acc, array[index], index, array);
    }
    return acc;
    };

    View Slide

  60. @MoOx
    60
    LIST IS A VARIANT TYPE
    let rec fold_left = (f, acc, list) =>
    switch (list) {
    | [] => acc
    | [x, ...rest] => fold_left(f, f(acc, x), rest)
    };

    View Slide

  61. @MoOx
    1. Basics
    2. Modules
    3. Functions
    4. Variants
    5. Interop
    61

    View Slide

  62. @MoOx
    How do we incrementally
    adopt Reason on an
    existing codebase?
    62
    INTEROP

    View Slide

  63. @MoOx
    63
    INTEROP: EXTERNAL MODULES
    [@bs.module "../myExistingJsModule"]
    external myExistingJsModule : string = "";
    Declare that it's a module
    located at "../myExistingModule"
    The module is of string type
    Js.log(myExistingJsModule);
    The module is only imported
    when used

    View Slide

  64. @MoOx
    64
    INTEROP: EXTERNAL MODULES
    // Generated by BUCKLESCRIPT VERSION 2.2.4, PLEASE EDIT WITH CARE
    'use strict';
    var MyExistingJsModule = require("../myExistingJsModule");
    console.log(MyExistingJsModule.myExistingJsModule);
    /* Not a pure module */

    View Slide

  65. @MoOx
    65
    INTEROP: CREATE AND READ JAVASCRIPT OBJECTS
    let myJsObject = {
    "name": "Matthias",
    "age": Js.Null.return(24)
    };
    Js.log(myJsObject##name);

    View Slide

  66. @MoOx
    66
    INTEROP: ACCESS THE JS STDLIB
    array
    |> Js.Array.map(item => item * 2);

    View Slide

  67. @MoOx
    ReasonReact
    67

    View Slide

  68. @MoOx
    68

    View Slide

  69. @MoOx
    69
    WHERE DOES REACT COME FROM?
    • Immutability
    • Functional
    approach
    • PropTypes

    View Slide

  70. @MoOx
    70
    WHERE DOES REACT COME FROM?
    Creator of React
    Jordan Walke wrote the
    first React prototype in
    SML

    View Slide

  71. @MoOx
    71
    REASONREACT HAS A LOT BAKED IN
    • Components
    • Router
    • Reducers
    • Subscriptions

    View Slide

  72. @MoOx
    72
    JSX
    prop
    optionalProps=?optionalValue
    boolProp=false
    />

    View Slide

  73. @MoOx
    73
    REASONREACT: BASIC COMPONENT
    let component = ReasonReact.statelessComponent("HelloWorld");
    let make = (~name, _children) => {
    ...component,
    render: (_self) =>

    (ReasonReact.string("Hello " ++ name))

    };

    View Slide

  74. @MoOx
    74
    REASONREACT: REDUCER COMPONENT
    Define the type of the state
    Define all possible actions
    type state = int;
    type action =
    | Increment
    | Decrement;
    let component = ReasonReact.reducerComponent("Counter");

    View Slide

  75. @MoOx
    75
    REASONREACT: REDUCER COMPONENT
    Return an update for each action
    can be
    Update, UpdateWithSideEffect, SideEffect …
    reducer: (action, state) =>
    switch (action) {
    | Increment => ReasonReact.Update(state + 1)
    | Decrement => ReasonReact.Update(state - 1)
    }

    View Slide

  76. @MoOx
    76
    REASONREACT: REDUCER COMPONENT
    Send actions in your render function
    render: ({state, send}) =>

    (ReasonReact.stringToElement(string_of_int(state)))
    send(Increment)) title="+" />
    send(Decrement)) title="-" />

    View Slide

  77. @MoOx
    77
    REASONREACT: INTEROP
    ReasonReact.wrapReasonForJs(/* ... */)
    ReasonReact.wrapJsForReason(/* ... */)

    View Slide

  78. @MoOx
    Sum up
    78

    View Slide

  79. @MoOx
    • Safer
    • Less bugs
    • Easy refactoring
    79
    SUM UP

    View Slide

  80. @MoOx
    We all come up with the
    wrong assumptions on
    our first pass at something
    80
    SUM UP

    View Slide

  81. @MoOx
    Fix your assumptions at
    the type level and let the
    compiler show you the way
    81
    SUM UP

    View Slide

  82. @MoOx
    Spaghetti Reason code is
    better than spaghetti JS
    82
    SUM UP

    View Slide

  83. @MoOx
    C’est une bonne raison
    pour utiliser Reason
    83
    SUM UP: ONE QUESTION

    View Slide

  84. @MoOx
    84
    Questions ?
    https://moox.io/
    @MoOx
    Maxime Thirouin

    Matthias Le Brun
    @bloodyowl
    Slides ripped from

    View Slide