let name = "Shritesh"let age = 25let greeting = `hello ${name}` // Strings onlylet message = j`hello $age years old, $name`
Functions
let greet =() =>"Hello"letrec factorial =n =>if n <= 1 { 1 } else { n * factorial(n - 1) }
let make = (~bread, ~cheese, ~meat) =>
j`$meat sandwich with $cheese cheese on $bread`
let sandwich = make(~cheese="feta", ~bread="flatbread", ~meat="lamb")
More features: Optional labels, explicit optionals, default values, uncurried functions.
Records
Nominal product types requiring type declaration
type person = {
name: string,
age: int
}
let shritesh = {name: "Shritesh", age: 25} // type is inferredlet olderShritesh = {...shritesh, age: shritesh.age + 1}
Mutation and ref
type player = {
name: string,
mutable score: int
}
let mario = {name: "Mario", score: 10}
mario.score = mario.score + 1
// built into the languagetyperef<'a> = {
mutable contents: 'a
}
let i = ref(0)
while i.contents < 10 {
Js.log(i.contents)
i := i.contents + 1
}
Objects
Structural, inferred, polymorphic product types; Compiles to JS Objects
let shritesh = {
"name": "Shritesh",
"nationality": "Nepali"
}
let zuko = {
"name": "Zuko",
"breed": "Persian"
}
let print =entity =>Js.log(entity["name"])
print(shritesh);
print(zuko);
Variants
Nominal sum types
type shape =
| Point
| Circle(float)
| Triangle({base: float, height: float})// inline record
| Rectangle(float, float)let area = shape => switch shape {
| Point =>0.0| Circle(r) =>Js.Math._PI*. r *. r
| Triangle(t) => t.base *. t.height /. 2.0| Rectangle(l, b) => l *. b
}
Rectangle(3.0, 3.0)->area->Js.log
let drawVegetable =color => switch color {
| #Green =>"lettuce"| #Red =>"radish"| #White =>"mushroom"
}
let drawFruit =color => switch color {
| #Yellow =>"banana"| #Red =>"cranberry"| #Green =>"avocado"
}
let color = #Red
let vegetable = drawVegetable(color)let fruit = drawFruit(color)
Arrays
ReScript uses Arrays by default. Indexing is syntatic sugar for Array.get
open Belt
let arr = [1, 2, 3]let first: option<int> = arr[0]
In OCaml and JS, Array.get doesn't return an option
// open Jslet arr = [1, 2, 3]let first: int = arr[0]
List
let l = list{1, 2, 3}
let isEmpty = switch l {
| list{} =>true| list{_head, ..._rest} =>false
}
More data structures will follow this pattern in the future
Control flow
if something { thenThis } else { thenThat }
if something { thenThis } // else { () } // implicitfor i in0to10 { Js.log(i) }
for i in10downto0 { Js.log(i) }
while condition { inner_loop() } // See ref example above
Destructuring and Pattern matching
Irrefutable patterns can be destructured
let coordinates = (1, 2, 0)
let (x, y, _) = coordinates
let sum = ((x, y, z)) = x + y + z // even in functions
Pattern matching using switch
switch Some(10) {
| Some(n)when n > 10 =>"More than ten"// when guard| Some(2) | Some(4) =>"Two or four"// multiple clauses| Some(_) =>"Not two, four or ten"| None =>"No number given"
}
Pipe (first)
Syntactic sugar for function application
let sum = (a, b, c) => a + b + c
let four = 1->sum(2, 1)
let addTwo = 1->sum(_, 1) // placeholderlet five = addTwo(3)let someFive = five->Some // Can pipe into variants!!!
|> is deprecated, heavier, pipes last and doesn't work with variants
Exceptions
Exceptional variants
exceptionOut_of(string)let chewBubblegum =() =>ifJs.Math.random() < 0.5 {
raise(Out_of("bubblegum"))
} else { "Kick Ass" }
try {
chewBubblegum()
} catch {
| Out_of(thing) =>"I'm all out of " + thing
}
switch chewBubblegum() {
| message => message
| exceptionOut_of(thing) =>"I'm all out of " + thing
}