ReasonML is a functional, strongly typed, programming language. It looks like JavaScript and compiles to JavaScript/Node as well as other languages. It is a dialect of OCaml and is compiled using BuckleScript. Therefore, you can use OCaml and BuckleScript APIs when using Reason.
If you want a more interactive example of ReasonML's language features, check out this link to the ReasonML REPL on their homepage: 👉 Click here 👈.
/* This is a comment whether single or multi-line */- Types are inferred. This means you don't have to declare types but you can if you want.
- Type coverage is 100%. Because types are inferred it means coverage is everywhere.
- Type system is sound. Compile and forget.
Types: list, array, string, char, bool, int, float, unit, option, etc.
Generics are created by putting a ' in front of an arbitrary variable name. However, it is most common to see single letters used.
let length: array('a) => int;Generics allow you to use a function in a more generic way. In the case of length, it's a function which takes an array of any type, 'a, and returns an int. In this instance, 'a can be a string, an int, or a record. What it enforces is that the array contains only that type. It can either be array(int) or array(string) but not both.
"A phantom type is a parametrised type whose parameters do not all appear on the right-hand side of its definition..." - Haskell Wiki, PhantomType
type formData('a) = string;Here formData is a phantom type as the 'a parameter only appears on the left side.
- Phantom Types in ReasonML by Ali Sharif
- Phantom Types in ReasonML by Kennet Postigo
An abstract type is a type without a concrete definition.
module type Person = {
type details;
let person: details;
let make: unit => details;
let greet: details => string;
} From the example above, the module declares the details type but leaves it to the module to define its implementation.
module Person: Person = {
type details = { name: string, age: int };
let person = { name: "Adam", age: 31};
let make = () => person;
let greet = (details) => "Hello. My name is " ++ details.name ++ " and I am " ++ string_of_int(details.age) ++ " years old.";
}
let adam = Person.make();
let greet = Person.greet(adam);Lists are created with square brackets:
let list: list(int) = [1, 2]let list1 = [1, 2, 3];
let list2 = [0, ...list1];
Js.log(list2); /* [0, 1, 2, 3] */* Can only use the spread operator once within a list
let list: list(int) = [1, 2, 3, 4];
let pm = (list): string => {
switch(list) {
| [] => "Empty"
| [head, ...tail] => {j|I only want $head|j}
}
};
Js.log(pm(list)); /* I only want 1 */Arrays are created with square brackets and pipes:
let arr: array(string) = [|"a", "b"|]Strings are created with double quotes:
let str: string = "Yeah, to you it's Thanksgiving; to me it's Thursday"Strings are concatenated with double plus signs:
let stringConcat: string = "Yo Adrian, " ++ "I did it!"String interpolation comes with help from BuckleScript:
let rocky: string = "Rocky"
let mickey: string = "Mickey"
let scene: string = {j|$mickey makes $rocky chase chickens to get in shape.|j}Characters are created using single quotes:
let char: char = 'a';
Js.log(char); /* 97 */let someFunction = () => "someFunction";let someFunction = () => {
() => {
"someAnonFunction"
}
};
Js.log(someFunction()()); /* "someAnonFunction" */let labeledArgs = (~arg1, ~arg2) => {
arg1 ++ arg2
};
Js.log(labeledArgs(~arg1="Some ", ~arg2="labeled args.")); /* "Some labeled args." */let labeledArgs = (~arg1 as one, ~arg2 as two) => {
one ++ two
};
Js.log(labeledArgs(~arg1="Some ", ~arg2="labeled args.")); /* "Some labeled args." */let labeledArgs = (~arg1="Some ", ~arg2=?, ()) =>
switch (arg2) {
| Some(arg) => arg1 ++ arg
| None => arg1 ++ "labeled args."
};
let res = labeledArgs(~arg2=?Some("labeled args"), ());
Js.log(res); /* Some labeled args. */let labeledArgs = (~arg1 as one, ~arg2 as two) => {
one ++ two
};
let firstArg = labeledArgs(~arg1="Some ");
let secondArg = firstArg(~arg2="labeled args.");
Js.log(secondArg); /* "Some labeled args." */* Doesn't matter which order you pass the labeled argument
let [a, b]: list(int) = [1, 2];let [|a, b|]: array(int) = [|1 , 2|];let (a, b): (int, int) = (1, 2);Use the switch to pattern match against values:
switch (value) {
| 1 => "one"
| _ => "Everything else"
};switch (1) {
| 1 => "one"
| _ => "Everything else"
};switch (option) {
| Some(option) => option
| None => None
};let arr: array(int) = [|1, 2, 3|];
let matchArr: array(int) => int = arr => {
switch (arr) {
| [|a, b, _|] => a + b
| [|a, b|] => a
| [|a|] => 0
| [||] => -1
| _ => 0
};
};
Js.log(matchArr(arr)); /* 3 */let arr = [|1, 2, 3|];
let matchArr: array(int) => int = (arr) =>
switch arr {
| [|a, b, _|] when a < 2 => a + b
| [|a, _, _|] when a > 2 => a
| [|a|] => 0
| [||] => (-1)
| _ => 0
};
Js.log(matchArr(arr)); /* 3 */type person = {
firstName: string,
lastName: string
};
let listOfPerson: list(person) = [{ firstName: "Rocky", lastName: "Balboa" }];type obj = {
.
color: string,
};
let car: obj = {
pub color = "Red"
};
Js.log(car#color); /* "Red" */* Objects in Reason are like constructors in JS
type obj('a) = {
..
color: string,
} as 'a;
let car: obj({. color: string, isRed: unit => bool }) = {
pub color = "Red";
pub isRed = () => this#getColor() == "Red";
pri getColor = () => this#color;
};
Js.log(car#isRed()); /* true */type person = {
.
"name": string,
[@bs.meth] "greet": unit => unit,
};
let printPerson = (p:person) => {
Js.log(p##name);
p##greet();
}type message: (int, string) = (200, "Success");type person =
| Rocky
| Mickey
| Adrian;
let matchPerson: person => string = (who: person) =>
switch who {
| Rocky => "Rocky"
| Mickey => "Mickey"
| Adrian => "Adrian"
};
Js.log(matchPerson(Rocky)); /* "Rocky" */| Symbol | Meaning |
|---|---|
| + | integer addition |
| +. | float addition |
| - | integer subtraction |
| -. | float subtraction |
| * | integer multiplication |
| *. | float mulitplication |
| / | integer division |
| /. | float division |
| ** | exponentation |
| |> | pipe / reverse application operator |
| @@ | application operator |
| ~+ | unary addition integer |
| ~+. | unary addition float |
| ~- | unary negation integer |
| ~-. | unary negation float |
| ++ | string concatenation |
| @ | list concatenation |
| -> | pipe first |
| Function | Meaning |
|---|---|
| Js.log | Logs value to console |
| Js.Float.isNaN | Checks to see if value is NaN |
| string_of_int | Convert integer into string |
| string_of_float | Convert float to string |