Pro Yearly is on sale from $80 to $50! »

Reason aka ReasonML

Reason aka ReasonML

Intro to ReasonML @devsmeetup Freiburg, April 2018

8977eabcedbade28ba0ebe0062e41c68?s=128

Erik Behrends

April 25, 2018
Tweet

Transcript

  1. add type safety and extra super powers to your JavaScript

    Erik Behrends @behrends
  2. Erik Behrends Prof @
 (Duale Hochschule Baden-Württemberg)
 (Baden-Wuerttemberg Cooperative State

    University) Teaching mobile app development 
 and other related programming topics
  3. We ❤ JavaScript it's used everywhere web (browser, server), apps

    (React Native, ionic), … quite easy to get started also offers functional programming techniques
  4. JS sometimes feels like "#$ JavaScript was designed in 2

    weeks and it shows… [] + []; // evaluates to "" ➞ weird language features we sometimes need to deal with undefined is not a function ➞ issues frequently slip into production code causing runtime errors
 (mainly due to JS being an interpreted lang with dynamic typing)
  5. Example: wrong code (but no error) let user = {

    name: "John", role: "reader" }; if (user.role = "admin") { // do something dangerous } // what's wrong with this code?
  6. Example: wrong code (but no error) let user = {

    name: "John", role: "reader" }; if (user.role = "admin") { // do something dangerous } // could be part of a larger code base // could even happen to experienced programmers: // copy/paste, mistyping, cat on keyboard, etc.
  7. let user = { name: "John", role: "reader" }; if

    (user.role = "admin") { // do something dangerous } // no syntax error in JavaScript // no runtime error // possibly some unintended effects ;-) Example: wrong code (but no error)
  8. ESLint: tool for static analysis (a linter) find errors at

    dev time, enforce styling guidelines
  9. Example: runtime error (TypeError) let john = { name: "John"

    }; let jane = { name: "Jane", city: { name: "Rome" } }; console.log(john.city.name); // again, might not be obvious in large code base
  10. let john = { name: "John" }; let jane =

    { name: "Jane", city: { name: "Rome" } }; console.log(john.city.name); // not detected by ESLint, leads to runtime error // Uncaught TypeError: 
 // Cannot read property 'name' of undefined Example: runtime error (TypeError)
  11. let john = { name: "John" }; let jane =

    { name: "Jane", city: { name: "Rome" } }; console.log(john.getCoordinates()); // another famous TypeError in JavaScript:
 // <something> is not a function // often seen as --> undefined is not a function Example: runtime error (TypeError)
  12. How to deal with this in JS? // data structure

    with optional fields (null, "") ?? let john = { name: "John", city: null }; let jane = { name: "Jane", city: { name: "Rome" } }; // null guard ??? if(john.city) console.log(john.city.name); // clever logical expression ??? console.log(john.city && john.city.name);
  13. Static typing to the rescue!? flow elm there are and

    will be more to choose from…
  14. % Decision Paralysis? & JavaScript fatigue?

  15. Let's talk about Reason (aka ReasonML)

  16. How would Reason handle the issues seen in the two

    examples?
  17. First example with JavaScript let user = { name: "John",

    role: "reader" }; if (user.role = "admin") { // do something dangerous } // reminder: // this is valid JavaScript! // no error at runtime!
  18. First example with Reason

  19. Second example with JavaScript let john = { name: "John"

    }; let jane = { name: "Jane", city: { name: "Rome" } }; console.log(john.city.name); // leads to runtime error // Uncaught TypeError: 
 // Cannot read property 'name' of undefined
  20. Second example with Reason

  21. What is Reason? Open sourced by Facebook in 2016. Reason

    is a new syntax and toolchain for OCaml. Not an extension of the JavaScript language.
 (unlike other approaches like TypeScript or flow).
  22. What is OCaml? OCaml is a functional language with pragmatic

    imperative aspects and object oriented elements. It has been developed for 20+ years, has a rock solid type system and many powerful features.
  23. OCaml OCaml Semantics (powerful type system and language features) OCaml

    Syntax (hard to get into when coming from other langs) Executable output either bytecode or native code
  24. Reason ∙ OCaml ∙ BuckleScript Reason Syntax (familiar to JavaScript

    devs for easy adoption) BuckleScript for JS output (generates readable, optimized JavaScript) OCaml Semantics (powerful type system and language features)
  25. Some of Reason's goals maximum, convenient type safety (by OCaml's

    type system) great interop with JavaScript (also work with npm/yarn) provide powerful functional programming paradigms first class support for React Reason's syntax makes this approachable for JavaScript devs
  26. Super Powers with Reason Automatic type inference Variants with pattern

    matching (and more)
  27. Automatic type inference Reason gets an excellent type system for

    free by being based on OCaml
  28. let pi = 3.14; let add = (a, b) =>

    a + b; type person = { name: string, mutable role: string, }; let user = {name: "John", role: "reader"}; let makeAdmin = someone => someone.role = "admin"; let printRole = somebody => { print_endline(somebody.name ++ " has this role:"); print_endline(somebody.role); }; often no need to annotate types — they are inferred automatically!
  29. CodeLens works with Reason in VS Code. Type information is

    displayed inline using type inference. (not part of source code, see line numbers)
  30. Types in Reason Type inference reduces syntactic overhead of static

    typing.
 (often no need to annotype types as they're inferred automatically) The type system is sound (incorrectly typed program won't compile).
 (removes whole categories of bugs & prevents runtime errors) Reason code has 100% type coverage.
 (thus code is implicitly documented & this is great for refactorings)
  31. Variants and pattern matching Reason docs call them “the crown

    juwel of Reason data structures”
  32. Goal: get rid of arbitrary cases type person = {

    name: string, role: string }; /* a role might be assigned any string value */ let user = {name: "John", role: "Reader"}; if (user.role == "Admin") { print_endline("now we do something dangerous"); }; Instead of allowing any string value for role, it would be great if we could explicitly define all its variants (Reader, Admin, etc.).
  33. type role = /* variant with only two possible values

    */ | Reader | Admin; type person = { name: string, role, }; let user = {name: "John", role: Reader}; if (user.role == Admin) { print_endline("now we do something dangerous"); }; Type role is called a Variant consisting of distinct construtors/tags. Now we can only use Reader and Admin when working with roles!
  34. let user = {name: "John", role: Reader}; let messageForUser =

    switch (user.role) { | Reader => "Go away!" | Admin => "Please enter..." }; print_endline(messageForUser); pattern matching with variant! type role = | Reader | Admin; type person = { name: string, role, };
  35. The compiler gives us a friendly and helpful warning. Imagine

    how useful this will be for refactorings. type role = | Reader | Editor | Admin; type person = { name: string, role, }; let's extend the variant with an Editor role…
  36. option is a variant that simulates “nullable” values. With pattern

    matching, there are no null errors in Reason! type role = | Reader | Editor | Admin; type person = { name: string, role: option(role) }; what if a person's role could be optional? let user = 
 {name: "John", role: Some(Reader)}; let user2 = {name: "Joe", role: None}; let messageForUser = user => switch (user.role) { | Some(Reader) => "Go away!" | Some(Editor) => "Your password?" | Some(Admin) => "Please enter..." | None => "How dare you asking..." };
  37. More super powers ✴first class modules: 
 every project file

    is a module, no need to require/import anything ✴great tooling (code formatting with refmt, REPL (rtop), friendly error messages) ✴blazing fast compile times (it's said to be much faster than TypeScript) ✴great interop with JavaScript, output is readable JS with dead code elimination ✴compiles to native code (possibly future React Native without JavaScript bridge?) ✴first level support for React (via ReasonReact: https://reasonml.github.io/reason-react/) ✴level up and learn about advanced language concepts (GADT, Phantom Types,…)
  38. Reason in production Facebook Messenger is developed with Reason: “Full

    rebuild of the Reason part of the codebase is ~2s (a few hundreds of files), incremental build (the norm) is <100ms on average.” “Messenger used to receive bugs reports on a daily basis; since the introduction of Reason, there have been a total of 10 bugs (that's during the whole year, not per week)!” https://reasonml.github.io/blog/2017/09/08/messenger-50-reason.html
  39. Drawbacks - Still in development, syntax might change (but there

    is a syntax upgrade tool) - Some new concepts to learn (might payoff in future) - You lose some flexibility (the price to pay for having static typing) - Don't expect that your code will be completely free from defects! - OCaml standard lib fragmentation (work in progress) - unicode not fully supported (workaround with BuckleScript possible) - async/await story still being worked on
  40. Summary • We want to detect and prevent issues in

    JavaScript code at dev time. • We have ESLint and many static typing tools to choose from. • Reason is a promising solution covering linting and static typing: ✓powerful type system (inference, soundness, coverage, …) ✓super useful extra features (variant, pattern matching, …) ✓enable JavaScript devs get started (syntax, toolchain, interop, …)
  41. Next steps with Reason ‣ Try Reason in browser: https://reasonml.github.io/en/try.html

    ‣ Book, free to read online: http://reasonmlhub.com/exploring-reasonml/ ‣ Articles/Videos: https://reasonml.github.io/docs/en/articles-and-videos.html ‣ Use Reason in some part of your app: ‣ Install: https://reasonml.github.io/docs/en/global-installation.html ‣ Convert JS: https://reasonml.github.io/docs/en/converting-from-js.html
 (check in both JS and Reason code into your VCS)
  42. Many thanks! ' www.behrends.io ( erik@behrends.io ) @behrends * speakerdeck.com/behrends

    (slides)