Reason
- File size
- 9.6KB
- Lines of code
- 249
Reason
Syntax and tooling extension on top of OCaml for reliable, maintainable software development with seamless JavaScript interoperability.
Comments
// ----- COMMENT -----
// this is a single-line comment
/* this is a
multi-line
comment */
Printing
// ----- PRINTING -----
// Js.log() => receives a string argument that is then printed to the stdout and includes a newline automatically
// note that there is no built-in implementation to display a string to the stdout without including a newline
Js.log("this includes a newline by default");
Quickstart
// ----- QUICKSTART -----
// semicolon-delimited functional language
// strongly, statically-typed with type inference for convenience
// high performance optimisation with strict type safety
// compiles to native bytecode or transpiles to JavaScript
// let => declares an immutable variable binding, note that Reason variables are immutable by default similar to Rust
// : => specifies the datatype of a given variable, providing type annotations for safety and expressiveness
// := => reassigns a new value to an existing mutable reference variable created with ref()
Types
// ----- TYPE -----
// int => stores an integer number value
// float => stores a floating-point number value
// string => stores a string value declared within "" double quotation marks, note that characters are handled as single-character long strings
// bool => true, false
// Option => specifies that a given value could either be of the specified datatype (and thereby Some) or the special value None
// Some => represents the presence of a value
// None => represents the absence of a value, the equivalent of void and null in other programming languages
// ref() => creates a mutable reference variable whose datatype is also specified within the () round brackets, and whose value can then be reassigned with :=
Operators
// ----- OPERATOR -----
// --- ARITHMETIC OPERATORS ---
+ // addition
- // subtraction
* // multiplication
/ // division
mod // modulo
// --- COMPARISON OPERATORS ---
== // thorough physical equality check for whether two objects have the same memory address
= // partial equality check for value but not type or memory address
!= // partial inequality check for value but not type or memory address
> // comparison operator
< // comparison operator
>= // comparison operator
<= // comparison operator
// --- LOGICAL OPERATORS ---
&& // logical and
|| // logical or
not() // logical not
Control structures
// ----- CONTROL STRUCTURE -----
// --- CONDITIONALS ---
// IF ELSE IF ELSE
// observe that as a functional language, the results of a conditional construct as below can be direcly assigned to a variable
let categorizeNumber = (n) => {
if (n < 0) {
"negative";
} else if (n == 0) {
"zero";
} else if (n > 0 && n < 10) {
"positive and less than 10";
} else {
"positive and 10 or greater";
}
};
// SWITCH | => _
// provides an advanced degree of pattern-matching, the equivalent of match case in Rust and select case in many other programming languages
// | => delimits each specified case and their corresponding execution code from the other cases
// _ => specifies the default fall-through case which executes if all other predicate case conditions fail to be met
// note that => specifies the relationship between a given predicate case condition and the execution code to be run if that case is met
let describeNumber = (x) => {
switch (x) {
| 0 => "zero"
| 1 => "one"
| _ => "many"
}
};
// --- LOOPS ---
// WHILE
// operates similarly to while loops in most other programming languages
let total = ref(0);
let i = ref(1);
while (!=(!i, 11)) {
total := !total + !i;
i := !i + 1;
Js.log(total);
};
// FOR IN
// allows for iteration and traversal over an iterable data structure
// operates similarly to for in loops in Python and foreach loops in PHP
for (i in 0 to 5) {
Js.log(i);
};
Data structures
// ----- DATA STRUCTURE -----
// list => fixed-size immutable singly-linked list traversed via recursion and enabling pattern-matching, declared within [] square brackets
// array => fixed-size mutable ordered collection of elements of the same datatype, the equivalent of lists in Python
// tuple => fixed-size immutable ordered collection of elements of multiple datatypes that affords powerful tuple destructuring, the equivalent of tuples in Python
// record => immutable user-defined collection of specified named fields and their corresponding datatypes, the equivalent of structs in Rust and Typescript, affording the modelling of representative data via type aliases
// variant => enumerated sun type that could be one of several user-defined types affording powerful pattern-matching, the equivalent of enums in Rust and Typescript
let anExampleList = [1, 2, 3, 4];
let anExampleArray = [|1, 2, 3, 4|];
let anExampleTuple = (1, "Hello", true);
let (x, y, z) = anExampleTuple; // tuple destructuring
type anExampleRecordOfAPerson = {
name: string,
age: int,
};
type threeDimensionalCoordinate = {
X: int,
Y: int,
Z: int,
};
type anExampleVariant =
| Circle(float)
| Rectangle(float, float);
let area = (s) => {
switch (s) {
| Circle(radius) => 3.14 *. radius *. radius
| Rectangle(width, height) => width *. height
}
};
Functions
// ----- FUNCTION -----
// functions are first-class citizens, allowing for the creation of user-defined higher-order functions
// while the syntax for creation of named and anonymous functions appear to be exactly the same as below, their use cases distinguish them from each other
// note that Reason inherits from functional programming paradigms, featuring implicit return of the last expression within the function
// let <functionName> = (<functionParameter(s)>) => <functionDefinitionBody> => definition and declaration of a named function, which are then called by their function name
// let <anonymousFunctionVariableIdentifier> = (<functionParameter(s)>) => <functionDefinitionBody> => definition of an anonymous function, which is then assigned to a named variable identifier
// also observe that anonymous functions can also be called directly in the same line as their definition
let add = (x, y) => x + y; // definition of a named function
let result1 = add(2, 3); // calling a named function
let result2 = add(3, 4); // calling a named function again
let result3 = add(4, 5); // calling a named function the last time
let subtract = (x, y) => x - y; // definition of an anonymous function
let result4 = subtract(5, 3); // calling an anonymous function
let resultDirect = ((x, y) => x * y)(4, 5); // anonymous function is declared and called in the same line
let applyFunction = (f, x) => f(x); // definition of a higher-order function
applyFunction((x) => x * x, 5); // calling a higher-order function