Learning to learn ReasonML

    
    LEARNING TO LEARN REASONML

    Jasim A Basheer 
    protoship.io

    @jasim_ab

 

Protoship Teleport

Protoship Codegen

Source data: Raw Vector Node

{
  x: 0,
  y: 64,
  name: "The classics are books",
  width: 600
  height: 63
}
{
  x: 0,
  y: 64,
  name: "The classics are books",
  width: 600
  height: 63
}
{
  nodeType: "text",
  marginLeft: 0,
  marginTop: 64,
  width: 600,
  height: 63
}
{
  nodeType: "text",
  marginLeft: 0,
  marginTop: 64,
  width: 600,
  height: 63
}
{
  nodeType: "text",
  marginLeft: {type: "px", value: 0},
  marginTop: {type: "px", value: 64},
  width: {type: "px", value: 600},
  height: {type: "px", value: 63}
}

 

Reason is released

AUTHOR
Jordan Walke (and Cheng Lou and others)

WROTE
React, Reason, and ReasonReact

The Talk

  • Reason: interesting bits
  • How does it feel to program
  • How to get started

Reason is OCaml

  • First released in 1990

  • C like speeds

  • ISWIM syntax (OCaml, Haskell) not ALGOL (C, Java, Javascript etc.)

let print_html_table segments =
  printf "<table>\n";
  List.iter (fun line ->
    printf "<tr>";
    List.iter (fun c -> printf "<td>%s</td>" (escape c)) line;
    printf "</tr>\n";
  ) segments;
  printf "</table>\n";
;;
let print_html_table segments =
  printf "<table>\n";
  List.iter (fun line ->
    printf "<tr>";
    List.iter (fun c -> printf "<td>%s</td>" (escape c)) line;
    printf "</tr>\n";
  ) segments;
  printf "</table>\n";
;;
let print_html_table = segments => {
  printf("<table>\n");
  List.iter(
    line => {
      printf("<tr>");
      List.iter(c => printf("<td>%s</td>", escape(c)), line);
      printf("</tr>\n");
    },
    segments,
  );
  printf("</table>\n");
};

What can we build with Reason/OCaml?

High-frequency trading software

 

World’s second largest crawler

 

Compilers

 

  • First version of the Rust compiler
  • Flow (typechecker for Javascript)
  • Hack (Facebook’s PHP compiler)

 

Front-end web applications!

 

Compile Reason into clean performant Javascript

OCaml has three compilers:

 

* ocamlc: produces executable binary

OCaml has three compilers:

 

* ocamlc: produces executable binary

* js_of_ocaml: produces Javascript, supports only OCaml libraries

OCaml has three compilers:

 

* ocamlc: produces executable binary

* js_of_ocaml: produces Javascript, supports only OCaml libs

* BuckleScript produces Javascript, and can use any npm package

BuckleScript

  • Clean performant Javascript
  • Build NodeJS applications
  • Build Browser applications

if (MomentRe.Moment.isSameWithGranularity(
      MomentRe.momentNow(),
      MomentRe.moment("2020-04-01"),
      `day,
    )) {
  Js.log("It is the 1st of April!");
} else {
  Js.log("A dreary day");
};
if (MomentRe.Moment.isSameWithGranularity(
      MomentRe.momentNow(),
      MomentRe.moment("2020-04-01"),
      `day,
    )) {
  Js.log("It is the 1st of April!");
} else {
  Js.log("A dreary day");
};
// Generated by BUCKLESCRIPT VERSION 5.0.6, PLEASE EDIT WITH CARE
'use strict';

var Moment = require("moment");
var MomentRe = require("bs-moment/src/MomentRe.js");

if (Moment().isSame(MomentRe.moment(undefined, "2020-04-01"), "day")) {
  console.log("It is the 1st of April!");
} else {
  console.log("A dreary day");
}

Paradigm

 

Reason/OCaml is a Typed Functional language

 

Reason/OCaml is a Typed Functional language

 

so is Elm, F#, Haskell, and PureScript

Hindley–Milner type system

Typed FP

has two principles:

1. Write pure functions

2. Get their types right

Perfection

The perfect computer program –

(a perfect program is) The one that does exactly what it should do, no more, no less, every time, with perfect reliability, and forever. The kind of perfection that you can get from mathematical definitions, which software is to a large extent, or from philosophical concepts.

“In search of software perfection”, by Dr. Xavier Leroy, author of OCaml

let showNext = lastUser => {
  console.log("You will be user " + (lastUser.id + 1))
}
showNext({id: 16})
You will be user 17
let showNext = u => {
  console.log("You will be user " + (u.id + 1))
}
showNext({id: null)
let showNext = u => {
  console.log("You will be user " + (u.id + 1))
}
showNext({id: null)
You will be user 1
let showNext = u => {
  console.log("You will be user " + (u.id + 1))
}
showNext({id: "193"})
let showNext = u => {
  console.log("You will be user " + (u.id + 1))
}
showNext({id: "193"})
You will be user 1931
let showNext = u => {
  console.log("You will be user " + (u.id + 1))
}
showNext({})
let showNext = u => {
  console.log("You will be user " + (u.id + 1))
}
showNext({})
You will be user NaN
let showNext = u => {
  console.log("You will be user " + (u.id + 1))
}
let users = []
let lastUserIndex = users.length - 1
let lastUser = users[lastUserIndex]

showNext(lastUser)
let showNext = u => {
  console.log("You will be user " + (u.id + 1))
}
let users = []
let lastUserIndex = users.length - 1
let lastUser = users[lastUserIndex]

showNext(lastUser)
Uncaught TypeError: Cannot read property 'id' of undefined
showNext()
showNext({id: "a"})
showNext({id: {}})
showNext(undefined)
showNext(null)
showNext(0)
showNext("a")
showNext([])
showNext([1])
showNext(a => a + 1)
showNext({id: 112})
You will be user 113
type user = {

}
type user = {
  id
}
type user = {
  id: int
};
type user = {
  id: int
};

let showNext = u => {
  Js.log("You will be user " ++ string_of_int(u.id + 1));
};
type user = {
  id: int
};

let showNext = u => {
  Js.log("You will be user " ++ string_of_int(u.id + 1));
};

showNext({id: 15});
You will be user 16
type user = { id: int };
let showNext = u => {
  Js.log("You will be user " ++ string_of_int(u.id + 1));
};
showNext({id: "abc"});

showNext({id: []});

showNext(a => a + 1);

type user = { id: int };

let showNext = u => {
  Js.log("You will be user " ++ string_of_int(u.id + 1));
};

showNext({id: 44});
showNext({id: 299});
showNext({id: -44});
You will be user 45
You will be user 300
You will be user -4

   

compile-time vs runtime errors

a stitch in time saves nine

Syntax errors are caught early

console.log("program started executing")
let text = Hello! This is a syntax error.

Syntax errors are caught early

console.log("program started executing")
let text = Hello! Is it Javascript you're looking for?
let text = Hello! This is a syntax error.
                ^
SyntaxError: Unexpected token !
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:617:28)
    at Object.Module._extensions..js (module.js:664:10)
    ...

   

Reason moves runtime errors into compile-time errors

as if they were syntax errors…

let showNext = lastUser => {
  console.log("You will be user " + (lastUser.id + 1))
}

let users = []
let lastUserIndex = users.length - 1
let lastUser = users[lastUserIndex]

showNext(lastUser)
let showNext = lastUser => {
  console.log("You will be user " + (lastUser.id + 1))
}

let users = []
let lastUserIndex = users.length - 1
let lastUser = users[lastUserIndex]

showNext(lastUser)
Uncaught TypeError: Cannot read property 'id' of undefined
type user = {id: int};

let showNext = u => {
  Js.log("You will be user " ++ string_of_int(u.id + 1));
};

let users = [||];  /* empty array */
let lastUserIndex = users[Array.length(users) - 1];
let lastUser = users[lastUserIndex];

showNext(lastUser);

switch(lastUser) {
  | None => Js.log("No users in the list")
  | Some(user) => showNext(user)
};

 

 

Refactor confidently!

 

 

Refactor confidently!

because if it compiles, it works

  if item == "tea"
    pourCoffee()
  else
    pourTea()

 

Logical mistakes are few,

clerical mistakes are many!

Dealing with external data

Ideas in Typed FP

Ideas in Typed FP

  • pure functional programming
    • light-weight syntax for currying and partial application
    • linked-lists over arrays
    • recursion over imperative loops

Ideas in Typed FP

  • sum types:
    • make invalid states impossible
  • no null, but option types!
  • exhaustive pattern matching

Ideas in Typed FP

  • expose concrete types rarely
  • interfaces before implementations

Learning Reason

A comparison

Concepts that carry over from Javascript to Reason

Javascript vs Reason

  • Javascript: this, variable hoisting, prototypes, ES6 classes, objects, mutations, functions, modules

  • Reason: functions, modules, types

How to learn

 

Start building UIs with ReasonReact

[@react.component]
let make = (~name) =>
  <button>
    {React.string("Hello!")}
  </button>;

   

Learn systematically

Don’t worry about immediate application

Learning Outline

  • Programming in the small
    • variables, data structures, iteration, functions

Learning Outline

  • Programming in the small
    • variables, data structures, iteration, functions

Learning Outline

  • Programming in the small
  • Tooling

Learning Outline

  • Tooling
    • VSCode + Reason plugin
    • Official setup instructions

Learning Outline

  • Programming in the large
    • modules

Book Recommendation

::: notes

The best resource for systematic study of OCaml is the book Real World OCaml. It uses the OCaml syntax, but that is easy to get used to. It is a great book because it teaches not only OCaml the language. You can also expect some very practical, very profound insights on programming as a whole, from this book.

::: notes

Systematic study

Closing thought

Is Reason ready for production?

Learning to learn ReasonML