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

37500337ba5d2aebc962959ed83928e5?s=128

Matthias Le Brun

September 14, 2017
Tweet

Transcript

  1. REASON or How I Learned to Stop Worrying and Learnt

    a New and Safer Language
  2. Matthias Le Brun twitter.com/bloodyowl github.com/bloodyowl

  3. JavaScript

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

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

    is less cool
  6. Why is that?

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

    instanceof …
  8. !!/** * @param {string} a * @param {string} b *

    @returns {string} #*/ const concat = (a, b) %=> a + b;
  9. concat({}, {}) !// NaN concat({}, []) !// "[object Object]" concat(1,

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

    "1") !// "11" concat(1, 1) !// 2 concat("1", "1") !// "11" MEDAL OF SUPER SAFETY
  11. Can we fix it?

  12. (/* @flow #*/ const concat = (a: string, b: string)

    %=> a + b; concat({}, {})
  13. None
  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
  15. None
  16. None
  17. MEDAL OF SUPER SAFETY

  18. OCaml

  19. 1996

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

  21. Only problem?

  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
  23. Syntax isn't really friendly to newcomers

  24. Here comes Reason

  25. 1 (/* int #*/ 1.0 (/* float #*/ "foo" (/*

    string #*/ 'a' (/* char #*/ [1, 2, 3] (/* list #*/ [| 1, 2, 3 |] (/* array #*/ Some 1 (/* option int #*/ Primitives
  26. int_of_string "1" string_of_float 1.0 Pervasives

  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
  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)
  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
  30. let sayHi ,::name ,::punct="!" () %=> "Hello " ^ name

    ^ punct; !// name,::string %=> string sayHi name,::"you" (); !// "Hello you!" sayHi name,::"you" punct,::"?" (); !// "Hello you?" Functions
  31. MyModule.foo (); MyModule.( foo () ); open MyModule; foo ();

    Modules
  32. module MyArray = { include Array; let double = map

    (fun x %=> x * 2); }; Modules
  33. module type MyModuleType = { type t; }; module MyModule

    (T: MyModuleType) %=> { let toList (value: T.t) %=> [value]; }; module MyStringModule = MyModule String; Functors
  34. type user = { name: string, age: int }; let

    user = { name: "Bob", age: 20 }; let olderUser = {…user, age: user.age + 1 }; Records
  35. None
  36. None
  37. type media = { url: string }; type message =

    | String string | Media media | Emoji char; Variants
  38. switch message { | String s %=> (/* … #*/

    | Media {url} %=> (/* … #*/ | Emoji c %=> (/* … #*/ } Pattern matching
  39. Pattern matching

  40. Pattern matching

  41. let value = { let a = 1; let b

    = 2; a + b }; Blocks
  42. Refactoring in JS: Refactoring in Reason:

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

  44. BuckleScript OCaml ➔ JavaScript

  45. It’s faster than vanilla™

  46. How?

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

  48. type user = { username: string, id: option string, age:

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

    id : Some #*/["abc"], (/* age #*/32 ]; Lightweight footprint
  50. [ "Bob", ["abc"], 32 ]; Lightweight footprint

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

    project from scratch
  52. Challenge accepted

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

  54. type user = { name: string, age: int }; let

    fromJs jsObject %=> { name: jsObject,##name, age: jsObject,##age }; Convert from JS
  55. let toJs object %=> { "name": object.name, "age": object.age };

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

  57. type message = | Image string | String string; let

    fromJs js %=> { switch js,##message_type { | "image" %=> Image js,##value | "string" | _ %=> String js,##value } } Complex conversions
  58. ReasonReact

  59. let component = ReasonReact.statelessComponent "App"; let make ,::message _children %=>

    { …component, render: fun _ %=> <div> (ReasonReact.stringToElement message) *</div> }; React
  60. type state = int; type actions = | Increment |

    Decrement; React
  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
  62. render: fun {state, reduce} %=> <div> (ReasonReact.stringToElement (string_of_int state)) <Button

    title="-" onClick=(reduce (fun _ %=> Increment)) 1/> *</div> React
  63. let message = "ok"; <MyComponent message onClick=(fun () %=> Js.log

    1) optionalProp=?optionalProp value=false 1/> JSX
  64. <div> (switch resource { | Loading %=> <ActivityIndicator 1/> |

    Idle value %=> <Component value 1/> | Error %=> ErrorMessage.serverError }) *</div> JSX
  65. module MyType = { let name = "Type"; type t

    = string; }; module MyTypeCollectionView = Primitives.FixedCollectionView.Make MyType; <MyTypeCollectionView items 1/> React
  66. let jsComponent = ReasonReact.wrapReasonForJs ,::component (fun jsProps %=> make message,::jsProps,##message

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

    React
  68. Demo

  69. More?

  70. Native compilation

  71. OCaml ➔ Native code ⚡

  72. let command = switch Sys.argv { | [|_, "watch"|] %=>

    Watch | [|_, "build"|] %=> Build | [|_, "help"|] | _ %=> Help }; Native
  73. In the end, what’s Reason?

  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
  75. None
  76. Thank you! Questions?