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

Reason or How I Learned to Stop Worrying and Learnt a New and Safer Language

Reason or How I Learned to Stop Worrying and Learnt a New and Safer Language

Matthias Le Brun

September 14, 2017
Tweet

More Decks by Matthias Le Brun

Other Decks in Programming

Transcript

  1. REASON
    or How I Learned to Stop
    Worrying and Learnt a New
    and Safer Language

    View Slide

  2. Matthias Le Brun
    twitter.com/bloodyowl
    github.com/bloodyowl

    View Slide

  3. JavaScript

    View Slide

  4. •Super easy to start making things
    •Very permissive
    •Everywhere
    JavaScript is cool

    View Slide

  5. •Super hard to get right
    •Very error prone
    •Hacky
    JavaScript is less cool

    View Slide

  6. Why is that?

    View Slide

  7. •Weakly typed
    •Dynamically typed
    •Very few data structures
    •Common-patterns: duck-typing,
    instanceof …

    View Slide

  8. !!/**
    * @param {string} a
    * @param {string} b
    * @returns {string}
    #*/
    const concat = (a, b) %=> a + b;

    View Slide

  9. concat({}, {}) !// NaN
    concat({}, []) !// "[object Object]"
    concat(1, "1") !// "11"
    concat(1, 1) !// 2
    concat("1", "1") !// "11"

    View Slide

  10. concat({}, {}) !// NaN
    concat({}, []) !// "[object Object]"
    concat(1, "1") !// "11"
    concat(1, 1) !// 2
    concat("1", "1") !// "11"
    MEDAL OF SUPER SAFETY

    View Slide

  11. Can we fix it?

    View Slide

  12. (/* @flow #*/
    const concat = (a: string, b: string) %=>
    a + b;
    concat({}, {})

    View Slide

  13. View Slide

  14. •Flow & TypeScript tools are good, but
    they aren’t as safe as we’d wish
    •Given JavaScript’s nature, it’ll always be
    hard to get that safety

    View Slide

  15. View Slide

  16. View Slide

  17. MEDAL OF SUPER SAFETY











    View Slide

  18. OCaml

    View Slide

  19. 1996

    View Slide

  20. •Strongly typed
    •Statically typed
    •Powerful type-inference
    •Good data structures

    View Slide

  21. Only problem?

    View Slide

  22. let rec qsort = function
    | [] *-> []
    | pivot ,:: rest *->
    let is_less x = x < pivot in
    let left, right = List.partition is_less rest in
    qsort left @ [pivot] @ qsort right

    View Slide

  23. Syntax isn't really friendly
    to newcomers

    View Slide

  24. Here comes Reason

    View Slide

  25. 1 (/* int #*/
    1.0 (/* float #*/
    "foo" (/* string #*/
    'a' (/* char #*/
    [1, 2, 3] (/* list #*/
    [| 1, 2, 3 |] (/* array #*/
    Some 1 (/* option int #*/
    Primitives

    View Slide

  26. int_of_string "1"
    string_of_float 1.0
    Pervasives

    View Slide

  27. let concat a b %=> a ^ b;
    !// string %=> string %=> string
    concat 1 "1";
    !// This expression has type int but an
    expression was expected of type string
    Functions

    View Slide

  28. let concat a b %=> a ^ b;
    !// string %=> string %=> string
    concat 1 "1";
    !// This expression has type int but an
    expression was expected of type string
    Functions

    (piece of cake)

    View Slide

  29. let add a b %=> a + b;
    !// int %=> int %=> int
    add 1 2;
    !// 3
    add 1 2.0;
    !// This expression has type float but an
    expression was expected of type int
    let addOne = add 1;
    !// int %=> int
    Functions

    View Slide

  30. let sayHi ,::name ,::punct="!" () %=>
    "Hello " ^ name ^ punct;
    !// name,::string %=> string
    sayHi name,::"you" ();
    !// "Hello you!"
    sayHi name,::"you" punct,::"?" ();
    !// "Hello you?"
    Functions

    View Slide

  31. MyModule.foo ();
    MyModule.(
    foo ()
    );
    open MyModule;
    foo ();
    Modules

    View Slide

  32. module MyArray = {
    include Array;
    let double = map (fun x %=> x * 2);
    };
    Modules

    View Slide

  33. module type MyModuleType = {
    type t;
    };
    module MyModule (T: MyModuleType) %=> {
    let toList (value: T.t) %=> [value];
    };
    module MyStringModule = MyModule String;
    Functors

    View Slide

  34. type user = { name: string, age: int };
    let user = { name: "Bob", age: 20 };
    let olderUser =
    {…user, age: user.age + 1 };
    Records

    View Slide

  35. View Slide

  36. View Slide

  37. type media = { url: string };
    type message =
    | String string
    | Media media
    | Emoji char;
    Variants

    View Slide

  38. switch message {
    | String s %=> (/* … #*/
    | Media {url} %=> (/* … #*/
    | Emoji c %=> (/* … #*/
    }
    Pattern matching

    View Slide

  39. Pattern matching

    View Slide

  40. Pattern matching

    View Slide

  41. let value = {
    let a = 1;
    let b = 2;
    a + b
    };
    Blocks

    View Slide

  42. Refactoring in JS:
    Refactoring in Reason:

    View Slide

  43. What’s it got to do
    with JavaScript?

    View Slide

  44. BuckleScript
    OCaml ➔ JavaScript

    View Slide

  45. It’s faster than vanilla™

    View Slide

  46. How?

    View Slide

  47. OCaml
    •Better data-structures
    •Fast standard algorithms

    View Slide

  48. type user = {
    username: string,
    id: option string,
    age: int
    };
    let user =
    {username: "Bob", id: Some "abc", age: 32};
    Lightweight footprint

    View Slide

  49. var user = (/* record #*/[
    (/* username #*/"Bob",
    (/* id : Some #*/["abc"],
    (/* age #*/32
    ];
    Lightweight footprint

    View Slide

  50. [
    "Bob",
    ["abc"],
    32
    ];
    Lightweight footprint

    View Slide

  51. Ok, sounds cool, but I don’t
    want to rewrite my project
    from scratch

    View Slide

  52. Challenge accepted

    View Slide

  53. external myExistingModule : string
    = [@@bs.module "#../myExistingModule"];
    Use JS

    View Slide

  54. type user = {
    name: string,
    age: int
    };
    let fromJs jsObject %=> {
    name: jsObject,##name,
    age: jsObject,##age
    };
    Convert from JS

    View Slide

  55. let toJs object %=> {
    "name": object.name,
    "age": object.age
    };
    Convert to JS

    View Slide

  56. {
    "message_type": "image" | "string",
    "value": string
    }
    Complex conversions

    View Slide

  57. type message =
    | Image string
    | String string;
    let fromJs js %=> {
    switch js,##message_type {
    | "image" %=> Image js,##value
    | "string"
    | _ %=> String js,##value
    }
    }
    Complex conversions

    View Slide

  58. ReasonReact

    View Slide

  59. let component =
    ReasonReact.statelessComponent "App";
    let make ,::message _children %=> {
    …component,
    render: fun _ %=>

    (ReasonReact.stringToElement message)
    *
    };
    React

    View Slide

  60. type state = int;
    type actions =
    | Increment
    | Decrement;
    React

    View Slide

  61. let component = ReasonReact
    .reducerComponent "App";
    let make _ %=> {
    …component,
    reducer: fun action state %=>
    switch action {
    | Increment %=> ReasonReact.Update (state + 1)
    | Decrement %=> ReasonReact.Update (state - 1)
    },
    (/* … #*/
    }
    React

    View Slide

  62. render: fun {state, reduce} %=>

    (ReasonReact.stringToElement
    (string_of_int state))
    title="-"
    onClick=(reduce (fun _ %=> Increment))
    1/>
    *
    React

    View Slide

  63. let message = "ok";
    message
    onClick=(fun () %=> Js.log 1)
    optionalProp=?optionalProp
    value=false
    1/>
    JSX

    View Slide


  64. (switch resource {
    | Loading %=>
    | Idle value %=>
    | Error %=> ErrorMessage.serverError
    })
    *
    JSX

    View Slide

  65. module MyType = {
    let name = "Type";
    type t = string;
    };
    module MyTypeCollectionView =
    Primitives.FixedCollectionView.Make MyType;

    React

    View Slide

  66. let jsComponent =
    ReasonReact.wrapReasonForJs
    ,::component
    (fun jsProps %=>
    make message,::jsProps,##message [,||]
    );
    React

    View Slide

  67. let make ,::message children %=>
    ReasonReact.wrapJsForReason
    ,::reactClass
    props,::{"message": message}
    children;
    React

    View Slide

  68. Demo

    View Slide

  69. More?

    View Slide

  70. Native compilation

    View Slide

  71. OCaml ➔ Native code

    View Slide

  72. let command =
    switch Sys.argv {
    | [|_, "watch"|] %=> Watch
    | [|_, "build"|] %=> Build
    | [|_, "help"|]
    | _ %=> Help
    };
    Native

    View Slide

  73. In the end, what’s Reason?

    View Slide

  74. • A new, simpler syntax for OCaml
    • Lots of efforts in improving tooling
    (BetterErrors, BuckleScript is a friend project)
    • New features like JSX
    • A new community (super active at the
    moment)
    • A great core team who knows what to
    prioritise first to make it good for everyone

    View Slide

  75. View Slide

  76. Thank you!
    Questions?

    View Slide