Skip to content

Commit 1cfb001

Browse files
committed
Add language overview page
1 parent 6747c3f commit 1cfb001

File tree

1 file changed

+351
-0
lines changed

1 file changed

+351
-0
lines changed

docs/overview.md

Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
# Overview
2+
3+
This is an overview of most language features in Reason. It does not explain
4+
them in detail, but should serve as a quick reference. Please see the guides
5+
on the left for additional details about each feature.
6+
7+
## Let Bindings
8+
9+
_Details: [Let Bindings](/let-bindings)_
10+
11+
Feature | Example
12+
--------------------------------|----------
13+
String value | `let hi = "Hello World";`
14+
Int value | `let count = 42;`
15+
Type annotation on binding | `let count: int = 42;`
16+
17+
- Note: Let bindings are immutable and cannot change once created.
18+
19+
## Built In Types
20+
21+
_Details: [Primitives](primitives)_
22+
23+
Feature | Example
24+
--------------------------------|----------
25+
Int | `let x: int = 10;`
26+
Float | `let x: float = 10.0;`
27+
Boolean | `let x: bool = false;`
28+
String | `let x: string = "ten";`
29+
Char | `let x: char = 'c';`
30+
Unit | `let x: unit = ();`
31+
Option | `let x: option(int) = Some(10);`
32+
Tuple | `let x: (int, string) = (10, "ten");`
33+
List | `let x: list(int) = [1, 2, 3];`
34+
Array | <code>let x: array(int) = [&#124;1, 2, 3&#124;];</code>
35+
Functions | `let x: (int, int) => int = (a, b) => a + b;`
36+
37+
## Strings
38+
39+
_Details: [Strings](primitives#strings)_
40+
41+
Feature | Example
42+
--------------------------------|----------
43+
String | `"Hello"`
44+
String concatenation | `"Hello " ++ "World"`
45+
Character | `'x'`
46+
Character at index | `let x = "Hello"; x.[2];`
47+
48+
- String Functions: [`module String`](https://reasonml.github.io/api/String.html)
49+
50+
## Numbers
51+
52+
- _Details: [Integer](primitives#integer)_
53+
- _Details: [Float](primitives#float)_
54+
55+
Feature | Example
56+
--------------------------------|----------
57+
Integer | `23`, `-23`
58+
Integer operations | `23 + 1 - 7 * 2 / 5`
59+
Integer modulo | `13 mod 2`
60+
Float | `23.0`, `-23.0`
61+
Float operations | `23.0 +. 1.0 -. 7.0 *. 2.0 /. 5.0`
62+
Float exponentiation | `2.0 ** 3.0`
63+
64+
## Booleans and Logical Operators
65+
66+
_Details: [Boolean](primitives#boolean)_
67+
68+
Feature | Example
69+
--------------------------------|----------
70+
Boolean Values | `true`, `false`
71+
Comparison | `>`, `<`, `>=`, `<=`
72+
Boolean operations | `!`, `&&`, <code>&#124;&#124;</code>
73+
Reference equality | `===`, `!==`
74+
Structural equality | `==`, `!=`
75+
76+
## If-Else Expressions
77+
78+
Feature | Example
79+
--------------------------------|----------
80+
If-Else expressions | `if (condition) { a; } else { b; }`
81+
Ternary expressions | `condition ? a : b;`
82+
83+
- Note: These are expressions and can be assigned to a variable:
84+
`let x = if (condition) { a; } else { b; };`
85+
86+
## Functions
87+
88+
_Details: [Functions](functions)_
89+
90+
Feature | Example
91+
--------------------------------|----------
92+
Function definition | `let divide = (a, b) => a / b;`
93+
Function calls | `divide(6, 2); // 3`
94+
Named arguments | `let divide = (~a, ~b) => a / b;`
95+
Calling named arguments | `divide(~a=6, ~b=2); // 3`
96+
Named argument punning | `divide(~a, ~b);`
97+
Recursive functions | `let rec infinite = () => infinite();`
98+
99+
### Advanced Functions
100+
101+
Feature | Example
102+
--------------------------------|----------
103+
Partial application | `let divideTen = divide(10); divideTen(5); // 2`
104+
Partially applying out of order | `let half = divide(_, 2); half(10); // 5`
105+
Optional arguments | `let print = (~prefix=?, text) => {...};`
106+
Optional arguments with default | `let divide = (~a=100, ~b) => a / b;`
107+
Function chaining (pipe) | <code>32 &#124;> half &#124;> half; // 8</code>
108+
109+
### Function Types
110+
111+
Feature | Example
112+
--------------------------------|----------
113+
Inline typing | `let divide = (a: int, b: int): int => a / b;`
114+
Standalone type | `type intFn = (int, int) => int;`
115+
Using standalone type | `let divide: intFn = (a, b) => a / b;`
116+
Typing optional arguments | `let print = (~prefix: option(string)=?, text) => {...};`
117+
118+
## Implicit Return
119+
120+
There is no `return` keyword in Reason. The last expression in a block or
121+
function definition is the returned value.
122+
123+
```reasonml
124+
let twentyThree = () => {
125+
let x = 10;
126+
let x = x + 10;
127+
/* x + 3 is the implicit return of the function. */
128+
x + 3;
129+
};
130+
```
131+
132+
## Basic Structures
133+
134+
_Details: [Basic Structures](basic-structures)_
135+
136+
Feature | Example
137+
--------------------------------|----------
138+
List (Immutable) | `[1, 2, 3]`
139+
List add to front | `[a1, a2, ...theRest]`
140+
List concat | `[a1, a2] @ theRest`
141+
Array (Mutable) | <code>[&#124;1, 2, 3&#124;]</code>
142+
Array access | <code>let arr = [&#124;1, 2, 3&#124;]; arr[1];</code>
143+
Tuples | `(1, "hello")`
144+
145+
- List Functions: [`module List`](https://reasonml.github.io/api/List.html)
146+
- Array Functions: [`module Array`](https://reasonml.github.io/api/Array.html)
147+
148+
## Maps and Sets
149+
150+
There are several different ways to interact with Maps and Sets depending on the
151+
specific environment being used. In standard Reason code there are `Map` and
152+
`Set` modules:
153+
154+
- [`module Map.Make`](https://reasonml.github.io/api/Map.Make.html)
155+
- [`module Set.Make`](https://reasonml.github.io/api/Set.Make.html)
156+
157+
When using BuckleScript `belt` exposes these modules:
158+
159+
- [`module Belt.Map`](https://bucklescript.github.io/bucklescript/api/Belt.Map.html)
160+
- [`module Belt.Set`](https://bucklescript.github.io/bucklescript/api/Belt.Set.html)
161+
162+
There are also other libraries that will provide their own implementation of
163+
these data structures. Check the style guide of the project you are
164+
working in to determine which module to use.
165+
166+
## Type Annotations
167+
168+
Any expression or argument may include a "type annotation". In most cases, type annotations
169+
are not necessary and the compiler will infer the types automatically. You may include
170+
type annotations to verify your own understanding against what the compiler infers.
171+
172+
Feature | Example
173+
--------------------------------|----------
174+
Expression type annotation | `let x = (expression: int)`
175+
Annotation on let binding | `let x: int = expression;`
176+
Argument/return value annotation| `let addOne = (a: int): int => a + 1;`
177+
178+
## Type Parameters
179+
180+
Types can be made generic with type parameters.
181+
182+
Feature | Example
183+
--------------------------------|----------
184+
Type parameters | `type pair('a, 'b) = ('a, 'b);`
185+
Annotation with parameters | `let x: pair(int, string) = (10, "ten");`
186+
String list | `let x: list(string) = ["Hello", "World"];`
187+
188+
## Records
189+
190+
_Details: [Records](records)_
191+
192+
Feature | Example
193+
--------------------------------|----------
194+
Record definition | `type t = {foo: int, bar: string};`
195+
Record creation | `let x = {foo: 10, bar: "hello"};`
196+
Record access | `x.foo;`
197+
Record spread | `let y = {...x, bar: "world"};`
198+
Destructuring | `let {foo, bar} = x;`
199+
Mutable record fields | `type t = {mutable baz: int}; let z = {baz: 10};`
200+
Mutable record updates | `z.baz = 23;`
201+
With type parameters | `type t('a) = {foo: 'a, bar: string};`
202+
203+
- Note: Record types are [nominal](https://en.wikipedia.org/wiki/Nominal_type_system). This means that two different record definitions (`type x = {...};`) with the exact same fields are not compatible. They cannot be used interchangeably and cannot be spread into each other.
204+
205+
## Variants
206+
207+
_Details: [Variants](variants)_
208+
209+
Variant types model values that may assume one of many known variations. This
210+
feature is similar to "enums" in other languages, but each variant form may
211+
optionally specify data that is carried along with it.
212+
213+
Feature | Example
214+
--------------------------------|----------
215+
Variant definition | <code>type t = &#124; Foo &#124; Bar;</code>
216+
Variants with args | <code>type t = &#124; Foo(string) &#124; Bar(int);</code>
217+
With type parameters | <code>type t('a) = &#124; One('a) &#124; Two('a, 'a);</code>
218+
Using a variant | `let x = Two("Hello", "World");`
219+
220+
## Options
221+
222+
_Details: [Options](options)_
223+
224+
Options are a built-in variant that represent the presence or absence of a
225+
value. It is similar to the concept of "nullable" values in other languages. Options
226+
are used often.
227+
228+
Feature | Example
229+
--------------------------------|----------
230+
Definition (already defined) | <code>type option('a) = &#124; None &#124; Some('a);</code>
231+
Value that is present | `let x = Some("Hello World");`
232+
Value that is absent | `let y = None;`
233+
234+
## Pattern Matching
235+
236+
Pattern matching is a very powerful feature in Reason. It matches against variants
237+
and ensures all cases are covered. Start matching using the `switch` keyword:
238+
239+
```reasonml
240+
switch (foo) {
241+
| Some(value) => doSomething(value)
242+
| None => error()
243+
}
244+
```
245+
246+
Feature | Example
247+
--------------------------------|----------
248+
Basic case | <code>&#124; Some(value) => doSomething(value)</code>
249+
When conditions | <code>&#124; Some(value) when value > 10 => doSomething(value)</code>
250+
Catch-all case | <code>&#124; _ => doSomething()</code>
251+
Matching lists | <code>&#124; [a, b, ...rest] => doSomething(rest)</code>
252+
Matching records | <code>&#124; {foo: value} => doSomething(value)</code>
253+
Matching literals | <code>&#124; "Hello" => handleHello()</code>
254+
255+
## Unit
256+
257+
The special "unit" value (written `()`) represents something that never has any
258+
meaningful value (this is distinct from options which may have a value).
259+
Functions usually indicate that they perform a side effect by returning a unit
260+
value.
261+
262+
Feature | Example
263+
--------------------------------|----------
264+
Creating a unit | `let x = ();`
265+
Passing to a function | `fn(a, b, ());`
266+
Unit as only argument | `let fn = () => 1; fn();`
267+
268+
## Refs
269+
270+
_Details: [Mutable Bindings](mutable-bindings)_
271+
272+
Refs allow mutable "variables" in your program. They are a thin wrapper around
273+
a record with a mutable field called `contents`.
274+
275+
Feature | Example
276+
--------------------------------|----------
277+
Type (already defined) | `type ref('a) = {mutable contents: 'a};`
278+
Ref creation | `let x = ref(10);` or `let x = {contents: 10};`
279+
Ref access | `x^;` or `x.contents;`
280+
Ref update | `x := 20;` or `x.contents = 20;`
281+
282+
## Loops
283+
284+
_Details: [Loops](loops.md)_
285+
286+
Loops are discouraged in most cases. Instead functional programming patterns
287+
like `map`, `filter`, or `reduce` can usually be used in their place.
288+
289+
Feature | Example
290+
--------------------------------|----------
291+
While | `while (condition) {...}`
292+
For (incrementing) | `for (i in 0 to 9) {...}` (inclusive)
293+
For (decrementing) | `for (i in 9 downto 0) {...}` (inclusive)
294+
295+
- Note: There is no `break` or early returns in Reason. Use a ref containing a
296+
bool for break-like behavior: `let break = ref(false); while (!break^ && condition) {...};`
297+
298+
## Modules
299+
300+
_Details: [Modules](modules)_
301+
302+
Modules are a way to group types and values. Each Reason file implicitly
303+
creates a module of the same name. Each `type` definition and `let` binding in
304+
a module automatically becomes a "member" of that module which can be accessed
305+
by other modules. Modules can also be nested using the `module` keyword.
306+
307+
Feature | Example
308+
--------------------------------|----------
309+
Module creation | `module Foo = { let bar = 10; };`
310+
Module member access | `Foo.bar;`
311+
Module types | `module type Foo = { let bar: int; };`
312+
313+
## Functors
314+
315+
Functors are like functions that create modules. This is an advanced topic
316+
that can be very powerful. Here is a basic example:
317+
318+
```reasonml
319+
module type Stringable = {
320+
type t;
321+
let toString: (t) => string;
322+
};
323+
324+
module Printer = (Item: Stringable) => {
325+
let print = (t: Item.t) => {
326+
print_endline(Item.toString(t));
327+
};
328+
329+
let printList = (list: list(Item.t)) => {
330+
list
331+
|> List.map(Item.toString)
332+
|> String.concat(", ")
333+
|> print_endline;
334+
};
335+
};
336+
337+
module IntPrinter = Printer({
338+
type t = int;
339+
let toString = string_of_int;
340+
});
341+
342+
IntPrinter.print(10); // 10
343+
IntPrinter.printList([1, 2, 3]); // 1, 2, 3
344+
```
345+
346+
## Comments
347+
348+
Feature | Example
349+
--------------------------------|----------
350+
Multiline Comment | `/* Comment here */`
351+
Single line Comment | `// Comment here`

0 commit comments

Comments
 (0)