12 | );
13 | }
14 |
15 | export default Card;
16 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const compression = require('compression');
3 | const path = require('path');
4 |
5 | const app = express();
6 | app.use(compression(9));
7 | app.use(express.static(path.join(__dirname, 'dist')));
8 | app.get('*', (req, res) =>
9 | res.sendFile(path.join(__dirname + '/dist/index.html')));
10 |
11 | app.listen(8000, () => console.log('🥅 RDN Listening on %j', 8000));
12 |
--------------------------------------------------------------------------------
/src/components/Resources/styles/Selection.css:
--------------------------------------------------------------------------------
1 | .selection{
2 | display: flex;
3 | }
4 | .selection .active {
5 | border-bottom: 1px solid #EB7E6C;
6 | padding: 20px;
7 | }
8 | .selection .inactive {
9 | border-bottom: 1px solid #E1E1E1;
10 | padding: 20px;
11 | }
12 | .selection .normalize-link, .selection .normalize-link p {
13 | color: black;
14 | margin: 0;
15 | }
16 | .selection .normalize-link:hover {
17 | color: black;
18 | }
--------------------------------------------------------------------------------
/src/components/Standalone/Markdown.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactMarkdown from 'react-markdown';
3 | import CodeBlock from './CodeBlock.js';
4 | import Link from './Link.js';
5 |
6 | function Markdown(props) {
7 | return (
8 |
15 | );
16 | }
17 |
18 | export default Markdown;
19 |
--------------------------------------------------------------------------------
/src/components/Standalone/Edit.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './styles/Edit.css';
3 |
4 | function Edit({ match }) {
5 | console.log(match);
6 | return (
7 |
16 | );
17 | }
18 |
19 | export default Edit;
20 |
--------------------------------------------------------------------------------
/src/components/Standalone/styles/Card.css:
--------------------------------------------------------------------------------
1 | .card {
2 | display: flex;
3 | flex-direction: column;
4 | border: 1px solid #F0F0F0;
5 | border-radius: .25rem;
6 | background-color: #fff;
7 | width: 210px;
8 | margin: 20px 0;
9 | padding: 10px 10px;
10 | }
11 | .card h3 {
12 | color: #434343;
13 | font-size: 1.5rem;
14 | font-weight: 400;
15 | margin: 5px 0;
16 | }
17 | .card p {
18 | color: #555555;
19 | margin: 2px 0;
20 | }
21 |
22 | .card a p{
23 | margin-top: 5px;
24 | margin-left: 0;
25 | text-align: left;
26 | color: #CE5643;
27 | }
--------------------------------------------------------------------------------
/documentation/native/reason/string/length.md:
--------------------------------------------------------------------------------
1 | # String.length
2 |
3 | The `length` operator is used to retrieve the length of a String.
4 |
5 | ### Parameters
6 |
7 | #### String
8 | The list whose length you want to retrieve.
9 |
10 | ### Return Value
11 | An integer representing the size of the string.
12 |
13 | ```
14 | let name = "John Doe";
15 |
16 | String.length name;
17 |
18 | /* returns 8 */
19 | ```
20 |
21 | ### String.length type definition
22 | ```
23 | let length : string => int
24 | ```
25 |
26 | ### Syntax
27 | ```
28 | String.length string
29 | ```
30 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/iter.md:
--------------------------------------------------------------------------------
1 | # String.iter
2 |
3 | The `iter` operator is used to apply a function to all characters of a string.
4 |
5 | ### Parameters
6 |
7 | #### function
8 | Function to apply on each character
9 |
10 | #### string
11 | strings who's characters will be passed to function.
12 |
13 | ### Return Value
14 | unit.
15 |
16 | ### iterate through strings
17 | ```
18 |
19 | ```
20 |
21 | ### String.iter type definition
22 | ```
23 | let iter : (char => unit) => string => unit
24 | ```
25 |
26 | ### Syntax
27 | ```
28 | String.iter function string
29 | ```
30 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/capitalize.md:
--------------------------------------------------------------------------------
1 | # String.capitalize
2 |
3 | The `capitalize` operator is used to capitalize a string.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | String to capitalize.
9 |
10 | ### Return Value
11 | string.
12 |
13 | ### Capitalize a string
14 | ```
15 | let username = "johndoedude";
16 |
17 | let capitalizedUsername = String.capitalize username;
18 |
19 | /* returns "Johndoedude" */
20 | ```
21 |
22 | ### String.capitalize type definition
23 | ```
24 | let capitalize : string => string
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | String.capitalize string
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/flatten.md:
--------------------------------------------------------------------------------
1 | # List.flatten
2 |
3 | The `flatten` flattens a lists nested lists. Is an alias for the concat operator.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list whos nested list will be flattened.
9 |
10 | ### flatten two list
11 | ```
12 | let numbs = [[1, 2, 3], [4, 5, 6]];
13 |
14 | let head = List.flatten numbs;
15 |
16 | /* returns [1, 2, 3, 4, 5, 6] */
17 | ```
18 |
19 | ### List.flatten type definition
20 | ```
21 | let flatten: list (list 'a) => list 'a;
22 | ```
23 |
24 | ### Syntax
25 | ```
26 | List.flatten [[list1], [list2], ..., [listN]];
27 | ```
28 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/rev.md:
--------------------------------------------------------------------------------
1 | # List.rev
2 |
3 | The `rev` operator reverses the elements of a list.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list containing the element you want to retrieve.
9 |
10 | ### Return Value
11 | The list in the reverse order.
12 |
13 | ### Reverse a list
14 | ```
15 | let brands = ["adidas", "puma", "jordans"];
16 |
17 | let head = List.rev brands;
18 |
19 | /* returns ["jordans", "puma", "adidas"] */
20 | ```
21 |
22 | ### List.rev type definition
23 | ```
24 | let rev: list 'a => list 'a;
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | List.rev [list]
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/hd.md:
--------------------------------------------------------------------------------
1 | # List.hd
2 |
3 | The `hd` operator retrieves the first element of a list.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list whose head you want to retrieve.
9 |
10 | ### Return Value
11 | The first element of the list that was passed as a parameter.
12 |
13 | ### Grab the "head" of a list
14 | ```
15 | let brands = ["adidas", "puma", "jordans"];
16 |
17 | let head = List.hd brands
18 |
19 | /* returns "adidas" */
20 | ```
21 |
22 | ### List.hd type definition
23 | ```
24 | let hd: list 'a => 'a;
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | List.hd [list]
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/escaped.md:
--------------------------------------------------------------------------------
1 | # String.escaped
2 |
3 | The `escaped` operator is used to represent special characters with escape sequences.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | strings that will be escaped.
9 |
10 | ### Return Value
11 | string.
12 |
13 | ### Escape a string
14 | ```
15 | let specialString = " ¿";
16 |
17 | let escapedString = String.escaped specialString;
18 |
19 | /* returns "\t\194\191" */
20 | ```
21 |
22 | ### String.escaped type definition
23 | ```
24 | let escaped : string => string
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | String.escaped string
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/uppercase.md:
--------------------------------------------------------------------------------
1 | # String.uppercase
2 |
3 | The `uppercase` operator is used to uppercase all characters in a string.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | String to uppercase.
9 |
10 | ### Return Value
11 | string.
12 |
13 | ### Uppercase a string
14 | ```
15 | let username = "johndoedude";
16 |
17 | let uppercasedUsername = String.uppercase username;
18 |
19 | /* returns "JOHNDOEDUDE" */
20 | ```
21 |
22 | ### String.uppercase type definition
23 | ```
24 | let uppercase : string => string
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | String.uppercase string
30 | ```
31 |
--------------------------------------------------------------------------------
/src/components/ToolChain/styles/Toolchain.css:
--------------------------------------------------------------------------------
1 | .toolchain hr {
2 | height: 1px;
3 | color: #ECECEC;
4 | background: #ECECEC;
5 | font-size: 0;
6 | border: 0;
7 | margin: 20px 0;
8 | }
9 | .tooling-banner {
10 | display: flex;
11 | height: 200px;
12 | width: 100%;
13 | color: #fff;
14 | background: #EB7E6C;
15 | align-items: center;
16 | justify-content: center;
17 | }
18 | .tooling-banner h1 {
19 | font-weight: 400;
20 | }
21 | .toolchain .link {
22 | margin: 10px 15px 15px 0px;
23 | margin-left: 0px;
24 | color: #EB7E6C;
25 | }
26 | .toolchain h2 {
27 | margin-top: 20px;
28 | }
--------------------------------------------------------------------------------
/documentation/native/reason/array/of_list.md:
--------------------------------------------------------------------------------
1 | # Array.of_list
2 |
3 | The `of_list` operator takes a list and returns a array.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list that will be used to turn into a array.
9 |
10 | ### Return Value
11 | A array with the contents of the list.
12 |
13 | ### convert list to array
14 | ```
15 | let numbs = [ 1, 2, 3, 4, 5 ];
16 |
17 | Array.of_list numbs;
18 |
19 | /* returns [| 1, 2, 3, 4, 5 |] */
20 | ```
21 |
22 | ### Array.of_list type definition
23 | ```
24 | let of_list: list 'a => array 'a;
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | Array.of_list [ list ];
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/iteri.md:
--------------------------------------------------------------------------------
1 | # String.iteri
2 |
3 | The `iteri` operator is used to apply a function to all index of each character of a string.
4 |
5 | ### Parameters
6 |
7 | #### function
8 | Function to apply on each character index.
9 |
10 | #### string
11 | strings who's character indices will be passed to function.
12 |
13 | ### Return Value
14 | unit.
15 |
16 | ### concatenate strings
17 | ```
18 |
19 | ```
20 |
21 | ### String.iter type definition
22 | ```
23 | let iteri : (int => char => unit) => string => unit
24 | ```
25 |
26 | ### Syntax
27 | ```
28 | String.iteri function string
29 | ```
30 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/to_list.md:
--------------------------------------------------------------------------------
1 | # Array.to_list
2 |
3 | The `to_list` operator takes an array and returns a list.
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The array that will be used to turn into a list.
9 |
10 | ### Return Value
11 | A list with the contents of the array.
12 |
13 | ### convert array to list
14 | ```
15 | let numbs = [| 1, 2, 3, 4, 5 |];
16 |
17 | Array.to_list numbs;
18 |
19 | /* returns [ 1, 2, 3, 4, 5 ] */
20 | ```
21 |
22 | ### Array.to_list type definition
23 | ```
24 | let to_list: array 'a => list 'a;
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | Array.to_list [| array |];
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/length.md:
--------------------------------------------------------------------------------
1 | # List.length
2 |
3 | The `length` operator is used to retrieve the length of a List.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list whose length you want to retrieve.
9 |
10 | ### Return Value
11 | An integer representing the size of the list.
12 |
13 | ```
14 | let weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
15 |
16 | List.length weekdays;
17 |
18 | /* returns 7 */
19 | ```
20 |
21 | ### List.length type definition
22 | ```
23 | let length: list 'a => int;
24 | ```
25 |
26 | ### Syntax
27 | ```
28 | List.length [ list ]
29 | ```
30 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/lowercase.md:
--------------------------------------------------------------------------------
1 | # String.lowercase
2 |
3 | The `lowercase` operator is used to lowercase all characters in a string.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | String to lowercase.
9 |
10 | ### Return Value
11 | string.
12 |
13 | ### Lowercase a string
14 | ```
15 | let uppercasedUsername = "JOHNDOEDUDE";
16 |
17 | let lowercasedUsername = String.lowercase uppercasedUsername;
18 |
19 | /* returns "johndoedude" */
20 | ```
21 |
22 | ### String.lowercase type definition
23 | ```
24 | let lowercase : string => string
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | String.lowercase string
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/make.md:
--------------------------------------------------------------------------------
1 | # String.make
2 |
3 | The `make` operator is used to create a string of a specified length.
4 |
5 | ### Parameters
6 |
7 | #### Length
8 | The length the newly created string should have.
9 |
10 | #### Char
11 | The character used to fill the string.
12 |
13 | ### Return Value
14 | A string.
15 |
16 | ### Use make to create a string
17 | ```
18 | let fiveCharString = String.make 5 'i';
19 |
20 | /* returns "iiiii" */
21 | ```
22 |
23 | ### String.make type definition
24 | ```
25 | let make : int => char => string
26 | ```
27 |
28 | ### Syntax
29 | ```
30 | String.make length char
31 | ```
32 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/length.md:
--------------------------------------------------------------------------------
1 | # Array.length
2 |
3 | The `length` operator is used to retrieve the length of a Array.
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The array whose length you want to retrieve.
9 |
10 | ### Return Value
11 | An integer representing the size of the array.
12 |
13 | ```
14 | let weekdays = [| "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" |];
15 |
16 | Array.length weekdays;
17 |
18 | /* returns 7 */
19 | ```
20 |
21 | ### Array.length type definition
22 | ```
23 | let length: array 'a => int;
24 | ```
25 |
26 | ### Syntax
27 | ```
28 | Array.length [| array |]
29 | ```
30 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/uncapitalize.md:
--------------------------------------------------------------------------------
1 | # String.uncapitalize
2 |
3 | The `uncapitalize` operator is used to uncapitalize a string.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | String to uncapitalize.
9 |
10 | ### Return Value
11 | string.
12 |
13 | ### Uncapitalize a string
14 | ```
15 | let capitalizedUsername = "Johndoedude";
16 |
17 | let uncapitalizedUsername = String.uncapitalize capitalizedusername;
18 |
19 | /* returns "johndoedude" */
20 | ```
21 |
22 | ### String.uncapitalize type definition
23 | ```
24 | let uncapitalize : string => string
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | String.uncapitalize string
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/concat.md:
--------------------------------------------------------------------------------
1 | # List.concat
2 |
3 | The `concat` concatenates a lists nested lists.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list whos nested list will be concatenated.
9 |
10 | ### Return Value
11 | A new list whose nested lists have been flattened.
12 |
13 | ### concat two list
14 | ```
15 | let numbs = [[1, 2, 3], [4, 5, 6]];
16 |
17 | let head = List.concat numbs;
18 |
19 | /* returns [1, 2, 3, 4, 5, 6] */
20 | ```
21 |
22 | ### List.concat type definition
23 | ```
24 | let concat: list (list 'a) => list 'a;
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | List.concat [[list1], [list2], ..., [listN]];
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/tl.md:
--------------------------------------------------------------------------------
1 | # List tl
2 |
3 | The `tl` operator retrieves every element except the first one.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list whose tail you want to retrieve.
9 |
10 | ### Return Value
11 | All the elements except the first of the list that was passed as a parameter.
12 |
13 | ### Grab the "tail" element of a list
14 | ```
15 | let brands = ["adidas", "puma", "jordans"];
16 |
17 | let head = List.tl brands
18 |
19 | /* returns ["puma", "jordans"] */
20 | ```
21 |
22 | ### List.tl type definition
23 | ```
24 | let tl: list 'a => list 'a;
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | List.tl [list]
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/append.md:
--------------------------------------------------------------------------------
1 | # List.append
2 |
3 | The `append` operator puts to lists together.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The original list.
9 |
10 | ### list
11 | The list being appended
12 |
13 | ### Return Value
14 | A new list made up of the two lists.
15 |
16 | ### append two list
17 | ```
18 | let num1 = [1, 2, 3];
19 |
20 | let num2 = [4, 5, 6];
21 |
22 | let head = List.append num1 num2;
23 |
24 | /* returns [1, 2, 3, 4, 5, 6] */
25 | ```
26 |
27 | ### List.append type definition
28 | ```
29 | let append: list 'a => list 'a => list 'a;
30 | ```
31 |
32 | ### Syntax
33 | ```
34 | List.append [list] [list]
35 | ```
36 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/copy.md:
--------------------------------------------------------------------------------
1 | # Array.copy
2 |
3 | The `copy` creates a copy of an array
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The array that will be used to create a new array from it's contents.
9 |
10 | ### Return Value
11 | A array with contents copied from the provided array.
12 |
13 | ### copy an arrays
14 | ```
15 | let numbs = [| 1, 2, 3, 4, 5, 6 7, 8, 9, 10 |];
16 |
17 | let numbsCopy = Array.copy numbs;
18 |
19 | /* returns [| 1, 2, 3, 4, 5, 6 7, 8, 9, 10 |] */
20 | ```
21 |
22 | ### Array.copy type definition
23 | ```
24 | let copy: array 'a => array 'a;
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | Array.copy [| array |];
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/string.md:
--------------------------------------------------------------------------------
1 | # String
2 |
3 | The String Module contains functions that operate on the `String` data structure.
4 | `String`'s are an immutable data structure that contains a fixed-length sequence of (single-byte) characters. These are used by default in Reason.
5 |
6 | #### Create a String
7 |
8 | ```
9 | let name = "John Doe";
10 | ```
11 |
12 | #### Type this string by inlining the type
13 |
14 | ```
15 | let name: string = "John Doe";
16 | ```
17 |
18 | #### Type the string once again using a type alias:
19 |
20 | ```
21 | type personName = string;
22 | let name: personName = "John Doe";
23 | ```
24 |
25 | ### Syntax
26 | ```
27 | "string text"
28 | ```
--------------------------------------------------------------------------------
/documentation/native/reason/string/init.md:
--------------------------------------------------------------------------------
1 | # String.init
2 |
3 | The `init` operator is used to initialize a string with char values.
4 |
5 | ### Parameters
6 |
7 | #### Length
8 | The length the newly created string should have.
9 |
10 | #### initializer
11 | Function that takes an integer as a parameter and returns a char.
12 |
13 | ### Return Value
14 | A string.
15 |
16 | ### Use init to create a string
17 | ```
18 | let fiveCharString = String.init 5 (fun i => 'a');
19 |
20 | /* returns "aaaaa" */
21 | ```
22 |
23 | ### String.init type definition
24 | ```
25 | let init : int => (int => char) => string
26 | ```
27 |
28 | ### Syntax
29 | ```
30 | String.init length initializer
31 | ```
32 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/concat.md:
--------------------------------------------------------------------------------
1 | # Array.concat
2 |
3 | The `concat` concatenates a list of nested arrays.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list whos nested arrays will be concatenated.
9 |
10 | ### Return Value
11 | A new array whose nested arrays have been flattened.
12 |
13 | ### concat two arrays
14 | ```
15 | let numbs = [ [| 1, 2, 3 |], [| 4, 5, 6 |] ];
16 |
17 | let head = Array.concat numbs;
18 |
19 | /* returns [| 1, 2, 3, 4, 5, 6 |] */
20 | ```
21 |
22 | ### Array.concat type definition
23 | ```
24 | let concat: list (array 'a) => array 'a;
25 | ```
26 |
27 | ### Syntax
28 | ```
29 | Array.concat [ [| array1 |], [| array2 |], ..., [| arrayN |] ];
30 | ```
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/rev_append.md:
--------------------------------------------------------------------------------
1 | # List.rev_append
2 |
3 | The `rev_append` reverses a list and puts them together. This operator is tail-recursive (more efficient).
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The original list that is reversed.
9 |
10 | ### list
11 | The list being appended
12 |
13 | ### rev_append two list
14 | ```
15 | let num1 = [1, 2, 3];
16 |
17 | let num2 = [4, 5, 6];
18 |
19 | let head = List.rev_append num1 num2;
20 |
21 | /* returns [3, 2, 1, 4, 5, 6] */
22 | ```
23 |
24 | ### List.rev_append type definition
25 | ```
26 | let rev_append: list 'a => list 'a => list 'a;
27 | ```
28 |
29 | ### Syntax
30 | ```
31 | List.rev_append [list] [list]
32 | ```
33 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/contains.md:
--------------------------------------------------------------------------------
1 | # String.contains
2 |
3 | The `contains` operator is used to check if a character is in a string.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | string used to check for the character.
9 |
10 | #### char
11 | The character to look for in the string
12 |
13 | ### Return Value
14 | boolean.
15 |
16 | ### Check if a string has the letter n
17 | ```
18 | let username = "johndoedude";
19 |
20 | let containsN = String.contains username 'n';
21 |
22 | /* returns true*/
23 | ```
24 |
25 | ### String.contains type definition
26 | ```
27 | let contains : string => char => bool
28 | ```
29 |
30 | ### Syntax
31 | ```
32 | String.contains string char
33 | ```
34 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/create_float.md:
--------------------------------------------------------------------------------
1 | # Array.create_float
2 |
3 | The `create_float` operator creates an array of a specified length with float values.
4 |
5 | ### Parameters
6 |
7 | #### length
8 | The length you want the array to be.
9 |
10 | ### Return Value
11 | The array with the specified length populated with float values.
12 |
13 | ### Generate an float array
14 | ```
15 | let threeFloats = Array.create_float 3;
16 |
17 | /* returns [| 2.40313530137e-320, 2.18084879584e-314, 2.18127058956e-314 |] */
18 | ```
19 |
20 | ### Array.create_float type definition
21 | ```
22 | let create_float: int => array float;
23 | ```
24 |
25 | ### Syntax
26 | ```
27 | Array.create_float int
28 | ```
29 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/nth.md:
--------------------------------------------------------------------------------
1 | # List.nth
2 |
3 | The `nth` operator retrieves the element at the specified index.
4 |
5 | ### Parameters
6 |
7 | #### list
8 | The list containing the element you want to retrieve.
9 |
10 | #### index
11 | The index of the element in the list.
12 |
13 | ### Return Value
14 | The value found at the index of the list.
15 |
16 | ### Grab the nth element of a list
17 | ```
18 | let brands = ["adidas", "puma", "jordans"];
19 |
20 | let middle = List.nth brands 1;
21 |
22 | /* returns "puma" */
23 | ```
24 |
25 | ### List.nth type definition
26 | ```
27 | let nth: list 'a => int => 'a;
28 | ```
29 |
30 | ### Syntax
31 | ```
32 | List.nth [ list ] index
33 | ```
34 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/make.md:
--------------------------------------------------------------------------------
1 | # Array.make
2 |
3 | The `make` operator creates an array of a specified length populated with a specified value.
4 |
5 | ### Parameters
6 |
7 | #### length
8 | The length you want the array to be.
9 |
10 | #### value
11 | The value you want the array to have.
12 |
13 | ### Return Value
14 | The array with the specified length populated with the specified value.
15 |
16 | ### Generate an array
17 | ```
18 | let tenOnes = Array.make 10 1;
19 |
20 | /* returns [| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 |] */
21 | ```
22 |
23 | ### Array.make type definition
24 | ```
25 | let make: int => 'a => array 'a;
26 | ```
27 |
28 | ### Syntax
29 | ```
30 | Array.make int value
31 | ```
32 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/list.md:
--------------------------------------------------------------------------------
1 | # List
2 |
3 | The List Module contains functions that operate on the `List` data structure.
4 | `List`'s are immutable collection data structure that is used most often and
5 | by default in Reason.
6 |
7 | #### Create a List
8 |
9 | ```
10 | let pets = ["dog", "cat", "rabbit"];
11 | ```
12 |
13 | #### Type this `List` by inlining the type
14 |
15 | ```
16 | let pets: list string = ["dog", "cat", "rabbit"];
17 | ```
18 |
19 | #### Type the list once again using a type alias:
20 |
21 | ```
22 | type indoorPets = list string;
23 | let pets: indoorPets = ["dog", "cat", "rabbit"];
24 | ```
25 |
26 | ### Syntax
27 | ```
28 | [element0, element1, ..., elementN]
29 | ```
--------------------------------------------------------------------------------
/documentation/native/reason/string/rindex.md:
--------------------------------------------------------------------------------
1 | # String.rindex
2 |
3 | The `rindex` operator is used to get the index of the last occurence of a specified character.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | strings that will be escaped.
9 |
10 | #### char
11 | The character whose index you want to retrieve
12 |
13 | ### Return Value
14 | integer.
15 |
16 | ### Find the index of a character in a string
17 | ```
18 | let username = "johndoedude";
19 |
20 | let findLastD = String.rindex username 'd';
21 |
22 | /* returns 9*/
23 | ```
24 |
25 | ### String.rindex type definition
26 | ```
27 | let rindex : string => char => int
28 | ```
29 |
30 | ### Syntax
31 | ```
32 | String.rindex string char
33 | ```
34 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/append.md:
--------------------------------------------------------------------------------
1 | # Array.append
2 |
3 | The `append` operator puts two arrays together.
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The original array.
9 |
10 | ### array
11 | The array being appended
12 |
13 | ### Return Value
14 | A new array whose nested arrays have been flattened.
15 |
16 | ### append two arrays
17 | ```
18 | let num1 = [| 1, 2, 3 |];
19 |
20 | let num2 = [| 4, 5, 6 |];
21 |
22 | let head = Array.append num1 num2;
23 |
24 | /* returns [| 1, 2, 3, 4, 5, 6 |] */
25 | ```
26 |
27 | ### Array.append type definition
28 | ```
29 | let append: array 'a => array 'a => array 'a;
30 | ```
31 |
32 | ### Syntax
33 | ```
34 | Array.append [| array |] [| array |]
35 | ```
36 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/index.md:
--------------------------------------------------------------------------------
1 | # String.index
2 |
3 | The `index` operator is used to get the index of the first occurence of a specified character.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | string used to find the index of a character.
9 |
10 | #### char
11 | The character whose index you want to retrieve
12 |
13 | ### Return Value
14 | integer.
15 |
16 | ### Find the index of a character in a string
17 | ```
18 | let username = "johndoedude";
19 |
20 | let findFirstD = String.index username 'd';
21 |
22 | /* returns 4*/
23 | ```
24 |
25 | ### String.index type definition
26 | ```
27 | let index : string => char => int
28 | ```
29 |
30 | ### Syntax
31 | ```
32 | String.index string char
33 | ```
34 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/init.md:
--------------------------------------------------------------------------------
1 | # Array.init
2 |
3 | The `init` operator creates an array of a specified length of values.
4 |
5 | ### Parameters
6 |
7 | #### length
8 | The length you want the array to be.
9 |
10 | #### initiator
11 | A function that returns the element at each index.
12 |
13 | ### Return Value
14 | The array with the specified length populated with values.
15 |
16 | ### initialize an array
17 | ```
18 | let generateOneToTen = Array.init 10 (fun i => i + 1);
19 |
20 | /* returns [| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |] */
21 | ```
22 |
23 | ### Array.init type definition
24 | ```
25 | let init: int => (int => 'a) => array 'a;
26 | ```
27 |
28 | ### Syntax
29 | ```
30 | Array.init int fun
31 | ```
32 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/array.md:
--------------------------------------------------------------------------------
1 | # Array
2 |
3 | The Array Module contains functions that operate on the `Array` data structure.
4 | `Array`'s are mutable collection data structure that is used to in Reason as an
5 | alternative to `Lists`.
6 |
7 | #### Create a Array
8 |
9 | ```
10 | let pets = [| "dog", "cat", "rabbit" |];
11 | ```
12 |
13 | #### Type this `Array` by inlining the type
14 |
15 | ```
16 | let pets: array string = [| "dog", "cat", "rabbit" |];
17 | ```
18 |
19 | #### Type the array once again using a type alias;
20 |
21 | ```
22 | type indoorPets = array string;
23 | let pets: indoorPets = [| "dog", "cat", "rabbit" |];
24 | ```
25 |
26 | ### Syntax
27 | ```
28 | [| element0, element1, ..., elementN |]
29 | ```
--------------------------------------------------------------------------------
/documentation/native/reason/string/concat.md:
--------------------------------------------------------------------------------
1 | # String.concat
2 |
3 | The `concat` operator is used to concatenate strings together.
4 |
5 | ### Parameters
6 |
7 | #### seperator
8 | seperator between strings being concatenated.
9 |
10 | #### list
11 | list of strings to concatenate together
12 |
13 | ### Return Value
14 | A string.
15 |
16 | ### concatenate strings
17 | ```
18 | let lastName = "Doe";
19 |
20 | let firstName = "John";
21 |
22 | let lastThenFirst = String.concat ", " [lastName, firstName];
23 |
24 | /* returns "Doe, John" */
25 | ```
26 |
27 | ### String.concat type definition
28 | ```
29 | let concat : string => string list => string
30 | ```
31 |
32 | ### Syntax
33 | ```
34 | String.concat seperator list
35 | ```
36 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/trim.md:
--------------------------------------------------------------------------------
1 | # String.trim
2 |
3 | The `trim` operator is used to apply a function to all character indices of a string and stores the result in a new string that is returned.
4 |
5 | ### Parameters
6 |
7 | #### function
8 | Function to apply on each character
9 |
10 | #### string
11 | strings who's characters and indices will be passed to function.
12 |
13 | ### Return Value
14 | string.
15 |
16 | ### Trim a string
17 | ```
18 | let name = " John Doe ";
19 |
20 | let trimmedName = String.trim name;
21 |
22 | /* returns "John Doe" */
23 | ```
24 |
25 | ### String.mapi type definition
26 | ```
27 | let trim : string => string
28 | ```
29 |
30 | ### Syntax
31 | ```
32 | String.trim string
33 | ```
34 |
--------------------------------------------------------------------------------
/src/components/Community/Community.md:
--------------------------------------------------------------------------------
1 | ### Discord
2 | The reason community is full awesome, helpful, and kind folks. If you need help getting started, solving issues,
3 | or want to know how to help hop on [Discord](https://discordapp.com/invite/reasonml) and say hi 👋🏽 !
4 |
5 | ### Freenode IRC
6 | Many developers also hang out in [#reasonml on Freenode](http://irc.lc/freenode/reasonml).
7 |
8 | ### Stack Overflow
9 | Many members of the community use Stack Overflow to ask questions. Read through the [existing questions](http://stackoverflow.com/questions/tagged/reactjs) tagged
10 | with **reasonml** or [ask your own](http://stackoverflow.com/questions/ask?tags=reasonml)!
11 |
12 | ### RDN Contributors
13 | + ...
14 |
15 | ### RDN Sponsors
16 | + ...
--------------------------------------------------------------------------------
/src/components/Community/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Edit from './../Standalone/Edit.js';
3 | import Languages from './../Standalone/Languages.js';
4 | import Markdown from './../Standalone/Markdown.js';
5 | import md from './Community.md';
6 | import './styles/Community.css';
7 |
8 | function Community(props) {
9 | return (
10 |
11 |
12 |
Community
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | );
23 | }
24 |
25 | export default Community;
26 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | RDN
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/map.md:
--------------------------------------------------------------------------------
1 | # String.map
2 |
3 | The `map` operator is used to apply a function to all characters of a string and stores the result in a new string that is returned.
4 |
5 | ### Parameters
6 |
7 | #### function
8 | Function to apply on each character
9 |
10 | #### string
11 | strings who's characters will be passed to function.
12 |
13 | ### Return Value
14 | string.
15 |
16 | ### map through strings characters
17 | ```
18 | let name = "John Doe";
19 | let capName = String.map (fun c => Char.uppercase c) name;
20 |
21 | /* returns "JOHN DOE" */
22 | ```
23 |
24 | ### String.map type definition
25 | ```
26 | let map : (char => char) => string => string
27 | ```
28 |
29 | ### Syntax
30 | ```
31 | String.map function string
32 | ```
33 |
--------------------------------------------------------------------------------
/documentation/native/reason/list/cons.md:
--------------------------------------------------------------------------------
1 | # List [x, ...l]
2 |
3 | The `...` operator is just the cons operator in new clothing, use it to append an element to a list.
4 |
5 | ### Parameters
6 |
7 | #### element
8 | The value to be added to the list.
9 |
10 | #### list
11 | The list you want the element to be appended to.
12 |
13 | ### Return Value
14 | A new list with the newly appended item.
15 |
16 | ### Add an element to the List
17 | ```
18 | let brands = ["adidas", "puma", "jordans"];
19 |
20 | let brandsWithNike = ["nike", ...brands];
21 |
22 | /* returns ["nike", "adidas", "puma", "jordans"] */
23 | ```
24 |
25 | ### ... type definition
26 | ```
27 | let cons: 'a => list 'a => list 'a;
28 | ```
29 |
30 | ### Syntax
31 | ```
32 | [element, ...list]
33 | ```
34 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/sub.md:
--------------------------------------------------------------------------------
1 | # String.sub
2 |
3 | The `sub` operator is used to get a substring of an existing string.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | The length the newly created string should have.
9 |
10 | #### start
11 | The index to start creating a new string from
12 |
13 | #### length
14 | The quantity of chars from the start to take from the original string.
15 |
16 | ### Return Value
17 | A string.
18 |
19 | ### create a substring from and existing string
20 | ```
21 | let name = "John Doe";
22 |
23 | let lastName = String.sub name 5 3;
24 |
25 | /* returns "Doe" */
26 | ```
27 |
28 | ### String.sub type definition
29 | ```
30 | let sub : string => int => int => string
31 | ```
32 |
33 | ### Syntax
34 | ```
35 | String.sub string start length
36 | ```
37 |
--------------------------------------------------------------------------------
/src/components/ToolChain/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Markdown from './../Standalone/Markdown.js';
3 | import Edit from './../Standalone/Edit.js';
4 | import Languages from './../Standalone/Languages.js';
5 | import Tooling from './Tooling.md';
6 | import './styles/Toolchain.css';
7 |
8 | function ToolChain(props) {
9 | return (
10 |
11 |
12 |
Tooling
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | );
23 | }
24 |
25 | export default ToolChain;
26 |
--------------------------------------------------------------------------------
/src/components/Home/styles/Home.css:
--------------------------------------------------------------------------------
1 | .home-banner {
2 | display: flex;
3 | height: 200px;
4 | width: 100%;
5 | color: #fff;
6 | background: #EB7E6C;
7 | align-items: center;
8 | justify-content: center;
9 | }
10 | .home-banner h1 {
11 | font-weight: 400;
12 | }
13 | .header {
14 | display: flex;
15 | align-items: flex-end;
16 | justify-content: center;
17 | }
18 | .header h2, a, a p{
19 | padding: 0;
20 | margin: 0 2px;
21 | }
22 | .header h2 {
23 | margin-bottom: 7px;
24 | }
25 | .header a p{
26 | margin-bottom: 8px;
27 | color: #CFCFCF;
28 | font-size: 12px;
29 | }
30 | .header a p:hover {
31 | color: #CE5643;
32 | }
33 | .section {
34 | display: flex;
35 | justify-content: space-around;
36 | width: 100%;
37 | flex-wrap: wrap;
38 | margin: -10px 0 25px 0;
39 | }
--------------------------------------------------------------------------------
/documentation/native/reason/string/get.md:
--------------------------------------------------------------------------------
1 | # String.get
2 |
3 | The `get` operator is used to retrieve the character of a String found at the specified index.
4 |
5 | ### Parameters
6 |
7 | #### String
8 | The string you want to retrieve the character from.
9 |
10 | #### Index
11 | The index of the char.
12 |
13 | ### Return Value
14 | A Char found at the index.
15 |
16 | ### Get a charachter from a string
17 | ```
18 | let name = "John Doe";
19 |
20 | String.get name 5;
21 |
22 | /* returns 'D' */
23 | ```
24 |
25 | ### Use shorthand get syntax
26 | ```
27 | let name = "John Doe";
28 |
29 | name.[5];
30 |
31 | /* returns 'D' */
32 | ```
33 |
34 | ### String.get type definition
35 | ```
36 | let get : string => int => char
37 | ```
38 |
39 | ### Syntax
40 | ```
41 | String.get string index
42 | ```
43 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/sub.md:
--------------------------------------------------------------------------------
1 | # Array.sub
2 |
3 | The `sub` returns a new array from a portion of the array that was provided.
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The array that will be used to create a new array from it's contents.
9 |
10 | #### start
11 | The initial index from the array.
12 |
13 | #### length
14 | The length from the starting index of values to take.
15 |
16 | ### Return Value
17 | A new array.
18 |
19 | ### sub an arrays
20 | ```
21 | let numbs = [| 1, 2, 3, 4, 5, 6 7, 8, 9, 10 |];
22 |
23 | let sixToTen = Array.sub numbs 5 5;
24 |
25 | /* returns [| 6, 7, 8, 9, 10 |] */
26 | ```
27 |
28 | ### Array.sub type definition
29 | ```
30 | let sub: array 'a => int => int => array 'a;
31 | ```
32 |
33 | ### Syntax
34 | ```
35 | Array.sub [| array |] start length;
36 | ```
37 |
--------------------------------------------------------------------------------
/src/components/Standalone/AsyncMarkdown.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Markdown from './Markdown.js';
3 |
4 | function asyncMarkdown(getMarkdown) {
5 | return class AsyncMarkdown extends Component {
6 | constructor(props) {
7 | super(props);
8 | this.MD = null;
9 | this.state = { MD: AsyncMarkdown.MD };
10 | }
11 |
12 | componentWillMount() {
13 | if (!this.state.MD) {
14 | getMarkdown().then(MD => {
15 | AsyncMarkdown.MD = MD;
16 | this.setState(() => ({ MD }));
17 | });
18 | }
19 | }
20 | render() {
21 | const { MD } = this.state;
22 | if (MD) {
23 | return ;
24 | }
25 | return null;
26 | }
27 | };
28 | }
29 |
30 | export default asyncMarkdown;
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/make_matrix.md:
--------------------------------------------------------------------------------
1 | # Array.make_matrix
2 |
3 | The `make_matrix` operator creates a two-dimensional array of a specified length of all indices are initialized to the same value.
4 |
5 | ### Parameters
6 |
7 | #### lengthX
8 | The length of the outer most array.
9 |
10 | #### lengthY
11 | The length of the nested arrays.
12 |
13 | #### value
14 | The value all indices are initialized to.
15 |
16 | ### Return Value
17 | A two-dimensional array.
18 |
19 | ### initialize an array
20 | ```
21 | let generateTwoByTwoOnes = Array.make_matrix 2 2 1;
22 |
23 | /* returns [| [|1, 1|], [|1, 1|] |] */
24 | ```
25 |
26 | ### Array.make_matrix type definition
27 | ```
28 | let make_matrix: int => int => 'a => array (array 'a);
29 | ```
30 |
31 | ### Syntax
32 | ```
33 | Array.make_matrix int int value
34 | ```
35 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/contains_from.md:
--------------------------------------------------------------------------------
1 | # String.contains_from
2 |
3 | The `contains_from` operator is used to check if a character is in a string after a specified index.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | string used to check for the character.
9 |
10 | #### index
11 | The index to start checking for the character.
12 |
13 | #### char
14 | The character to look for in the string.
15 |
16 | ### Return Value
17 | boolean.
18 |
19 | ### Check if a string has the letter n after and index
20 | ```
21 | let username = "johndoedude";
22 |
23 | let containsN = String.contains_from username 4 'n';
24 |
25 | /* returns false*/
26 | ```
27 |
28 | ### String.contains_from type definition
29 | ```
30 | let contains_from : string => int => char => bool
31 | ```
32 |
33 | ### Syntax
34 | ```
35 | String.contains_from string index char
36 | ```
37 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/index_from.md:
--------------------------------------------------------------------------------
1 | # String.index_from
2 |
3 | The `index_from` operator is used to get the index of the first occurence of a specified character after an index.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | string used to find the index of the character.
9 |
10 | #### index
11 | The index to start looking for the character at.
12 |
13 | #### char
14 | The character whose index you want to retrieve
15 |
16 | ### Return Value
17 | integer.
18 |
19 | ### Find the index of a character in a string
20 | ```
21 | let username = "johndoedude";
22 |
23 | let findDFromIndex = String.index_from username 5 'd';
24 |
25 | /* returns 7*/
26 | ```
27 |
28 | ### String.index_from type definition
29 | ```
30 | let index_from : string => int => char => int
31 | ```
32 |
33 | ### Syntax
34 | ```
35 | String.index_from string index char
36 | ```
37 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/rindex_from.md:
--------------------------------------------------------------------------------
1 | # String.rindex_from
2 |
3 | The `rindex_from` operator is used to get the index of the last occurence of a specified character after an index.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | string used to find the index of the character.
9 |
10 | #### index
11 | The index to start looking for the character at.
12 |
13 | #### char
14 | The character whose index you want to retrieve
15 |
16 | ### Return Value
17 | integer.
18 |
19 | ### Find the index of a character in a string
20 | ```
21 | let username = "johndoedude";
22 |
23 | let findDFromIndex = String.rindex_from username 8 'd';
24 |
25 | /* returns 7*/
26 | ```
27 |
28 | ### String.rindex_from type definition
29 | ```
30 | let rindex_from : string => int => char => int
31 | ```
32 |
33 | ### Syntax
34 | ```
35 | String.rindex_from string index char
36 | ```
37 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/rcontains_from.md:
--------------------------------------------------------------------------------
1 | # String.rcontains_from
2 |
3 | The `rcontains_from` operator is used to check for the last occurance of a character in a string after a specified index.
4 |
5 | ### Parameters
6 |
7 | #### string
8 | string used to check for the character.
9 |
10 | #### index
11 | The index to start checking for the character.
12 |
13 | #### char
14 | The character to look for in the string.
15 |
16 | ### Return Value
17 | boolean.
18 |
19 | ### Check if a string has the letter n after and index
20 | ```
21 | let username = "johndoedude";
22 |
23 | let containsN = String.rcontains_from username 4 'n';
24 |
25 | /* returns true*/
26 | ```
27 |
28 | ### String.rcontains_from type definition
29 | ```
30 | let rcontains_from : string => int => char => bool
31 | ```
32 |
33 | ### Syntax
34 | ```
35 | String.rcontains_from string index char
36 | ```
37 |
--------------------------------------------------------------------------------
/documentation/native/reason/string/mapi.md:
--------------------------------------------------------------------------------
1 | # String.mapi
2 |
3 | The `mapi` operator is used to apply a function to all character indices of a string and stores the result in a new string that is returned.
4 |
5 | ### Parameters
6 |
7 | #### function
8 | Function to apply on each character
9 |
10 | #### string
11 | strings who's characters and indices will be passed to function.
12 |
13 | ### Return Value
14 | string
15 |
16 | ### map through strings characters
17 | ```
18 | let yo = "yoyoyoyoyo";
19 |
20 | let stringMod i c =>
21 | if (i mod 2 == 0) {
22 | Char.uppercase c
23 | } else {
24 | c
25 | };
26 |
27 | let superYo = String.mapi stringMod yo;
28 |
29 | /* returns "YoYoYoYoYo" */
30 | ```
31 |
32 | ### String.mapi type definition
33 | ```
34 | let mapi : (int => char => char) => string => string
35 | ```
36 |
37 | ### Syntax
38 | ```
39 | String.mapi function string
40 | ```
41 |
--------------------------------------------------------------------------------
/src/components/Standalone/AsyncComponent.js:
--------------------------------------------------------------------------------
1 | // Originally Authored by Andrew Clark @acdlite
2 | import React, { Component } from 'react';
3 |
4 | function asyncComponent(getComponent) {
5 | return class AsyncComponent extends Component {
6 | constructor(props) {
7 | super(props);
8 | this.Component = null;
9 | this.state = { Component: AsyncComponent.Component };
10 | }
11 |
12 | componentWillMount() {
13 | if (!this.state.Component) {
14 | getComponent().then(Component => {
15 | AsyncComponent.Component = Component;
16 | this.setState(() => ({ Component }));
17 | });
18 | }
19 | }
20 | render() {
21 | const { Component } = this.state;
22 | if (Component) {
23 | return ;
24 | }
25 | return null;
26 | }
27 | };
28 | }
29 |
30 | export default asyncComponent;
31 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/fill.md:
--------------------------------------------------------------------------------
1 | # Array.fill
2 |
3 | The `fill` mutates an arrays contents from a starting point.
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The array that will be used to fill specified indices with a value.
9 |
10 | #### starting
11 | The index to start with filling its content with the specified value.
12 |
13 | #### length
14 | The amount of indeces to fill from the starting point.
15 |
16 | #### value
17 | The value to fill the indices with
18 |
19 | ### Return Value
20 | unit()
21 |
22 | ### fill an arrays contents
23 | ```
24 | let numbs = [| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |];
25 |
26 | let numbsCopy = Array.fill numbs 0 5 0;
27 |
28 | /* returns [| 0, 0, 0, 0, 0, 6, 7, 8, 9, 10 |] */
29 | ```
30 |
31 | ### Array.fill type definition
32 | ```
33 | let fill: array 'a => int => int => 'a => unit;
34 | ```
35 |
36 | ### Syntax
37 | ```
38 | Array.fill [| array |] starting length value;
39 | ```
40 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/get.md:
--------------------------------------------------------------------------------
1 | # Array.get
2 |
3 | The `get` operator retrieves the element at the specified index.
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The array containing the element you want to retrieve.
9 |
10 | #### index
11 | The index of the element in the array.
12 |
13 | ### Return Value
14 | The value found at the index of the array.
15 |
16 | ### Grab the nth element of a array
17 | ```
18 | let brands = [| "adidas", "puma", "jordans" |];
19 |
20 | let middle = Array.get brands 1;
21 |
22 | /* returns "puma" */
23 | ```
24 |
25 | ### Grab the nth element of a array with short syntax
26 | ```
27 | let brands = [| "adidas", "puma", "jordans" |];
28 |
29 | let middle = brands.(1);
30 |
31 | /* returns "puma" */
32 | ```
33 |
34 | ### Array.get type definition
35 | ```
36 | let get: array 'a => int => 'a;
37 | ```
38 |
39 | ### Syntax
40 | ```
41 | Array.get [| array |] index
42 |
43 | array.(index);
44 | ```
45 |
--------------------------------------------------------------------------------
/documentation/native/reason/introduction.md:
--------------------------------------------------------------------------------
1 | # Reason
2 |
3 | The Reason reference serves as a repository of facts about the Reason Toolchain. The entirety of reason is described here in detail. As you write Reason code, you'll refer to these pages often. If you're learning Reason, or need help understanding some of its capabilities or features, check out the [Reason guide](/reader/guides/native/anIntroductionToReason/introduction).
4 |
5 | The Reason Toolchain is intended to be cross-platform, be it a browser, server-side scripts, native, or similar. For the most part, this reference attempts to be environment-agnostic and does not target any particular environment.
6 |
7 | This documentation is broken up into sections. These sections are comprised from:
8 | + Data Structures
9 | + Data Types
10 | + OCaml Standard Library Modules
11 |
12 | Each of these sections will contain reference documentation that documents usage and examples of these and functions on these.
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/coreLanguage/objects.md:
--------------------------------------------------------------------------------
1 | # Objects \(WIP\)
2 |
3 | > If you haven't read the [Core Language Overview](/reader/guides/native/anIntroductionToReason/coreLanguage/coreLanguage) please do before diving deeper.
4 |
5 | ### Reason Objects
6 |
7 | Reason supports programming with Classes and construct Objects from classes. However, Reasons Object Oriented Programming model is different from the model C++, Java, etc. because you can use standalone objects without classes. Classes are used in Reason to enable inheritance. Objects also have object types that can determine whether an object is open or closed.
8 |
9 | ```reason
10 | Reason # let car = {
11 | val mutable isMoving = false;
12 | pub drive => isMoving = true;
13 | pub getState => isMoving;
14 | };
15 | let car : < drive : unit, getState : bool > =
16 |
17 | Reason # car#drive;
18 | - : unit = ()
19 |
20 | Reason # car#getState;
21 | - : bool = true
22 | ```
23 |
24 |
25 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/set.md:
--------------------------------------------------------------------------------
1 | # Array.set
2 |
3 | The `set` modifies the array at the specified index in place.
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The array containing the element you want to retrieve.
9 |
10 | #### index
11 | The index of the element in the array.
12 |
13 | #### value
14 | The desired value the index should be set to.
15 |
16 | ### Return Value
17 | The value found at the index of the array.
18 |
19 | ### Set the nth element of a array
20 | ```
21 | let brands = [| "adidas", "puma", "jordans" |];
22 |
23 | let middle = Array.set brands 1 "nike";
24 |
25 | /* returns unit() */
26 | ```
27 |
28 | ### Set the nth element of a array with short syntax
29 | ```
30 | let brands = [| "adidas", "puma", "jordans" |];
31 |
32 | brands.(1) = "nike";
33 |
34 | /* returns unit() */
35 | ```
36 |
37 | ### Array.get type definition
38 | ```
39 | let set: array 'a => int => 'a => unit;
40 | ```
41 |
42 | ### Syntax
43 | ```
44 | Array.set [| array |] index value
45 |
46 | array.(index) = value;
47 | ```
48 |
--------------------------------------------------------------------------------
/documentation/native/reason/array/blit.md:
--------------------------------------------------------------------------------
1 | # Array.blit
2 |
3 | The `blit` copies elements from one array to another array.
4 |
5 | ### Parameters
6 |
7 | #### array
8 | The array whos elements will be copied into the second array.
9 |
10 | #### starting
11 | The indice to start copying elements from.
12 |
13 | #### array2
14 | The array that will received the copied elements
15 |
16 | #### starting2
17 | The indice to start placing the copied values into.
18 |
19 | #### length
20 | The length to placed the copied values into.
21 |
22 | ### Return Value
23 | unit()
24 |
25 | ### copy an arrays contents into another array
26 | ```
27 | let oneToFive = [| 1, 2, 3, 4, 5 |];
28 |
29 | let sixToTen = [| 6, 7, 8, 9, 10 |];
30 |
31 | Array.blit oneToFive 0 sixToTen 0 5;
32 |
33 | /* sixToTen is now [| 1, 2, 3, 4, 5 |] */
34 | ```
35 |
36 | ### Array.blit type definition
37 | ```
38 | let blit: array 'a => int => array 'a => int => int => unit;
39 | ```
40 |
41 | ### Syntax
42 | ```
43 | Array.blit [| array |] starting [| array2 |] starting2 length;
44 | ```
45 |
--------------------------------------------------------------------------------
/src/components/Resources/Listing.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Card from './../Standalone/Card.js';
3 | import asyncMarkdown from './../Standalone/AsyncMarkdown';
4 | import './styles/Listing.css';
5 |
6 | function Listing({ category, technology, listing }) {
7 | const test = (category, technology, key) => {
8 | var Markdown = asyncMarkdown(() =>
9 | import(`./../../../${category}/${technology}/${key}/meta.md`)
10 | .then(module => module, err => console.log(err))
11 | );
12 | return
13 | };
14 |
15 | return (
16 |
35 |
36 |
37 | );
38 | }
39 |
40 | export default Navbar;
41 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/types/types.md:
--------------------------------------------------------------------------------
1 | # Types
2 |
3 | One of Reason's major benefits is its powerful type system that it inherits from OCaml. OCaml's type system is great and has powered many tools like flow that add static types to Javascript. Now I know what you may be thinking, but types in Reason are not painful like the ones you may have encountered in Java.
4 |
5 | In Reason types can be defined in many ways and optionally included in your code _almost_ always, this is possible because Reason is able to infer the types in your code:
6 |
7 | ```reason
8 | Reason # let kewlMath = fun (x, y) => x + y ;
9 | let kewlMath : (int, int) => int =
10 |
11 | Reason # let addForDays = kewlMath(5,5);
12 | let addForDays : int = 10
13 | ```
14 |
15 | As you can see Reason automatically infers what types the parameter is and the return type of the function. Reason is smart enough to know this and will catch your errors and notify you about them immediately as well:
16 |
17 | ```reason
18 | Reason # let addForDays = kewlMath(5, true);
19 | Error: This expression has type bool but an expression was expected of type
20 | int
21 | ```
22 |
23 | Reason will save you many hours of your precious time debugging. It provides really helpful errors and feedback to get you on the right track and squash bugs.
24 |
--------------------------------------------------------------------------------
/src/components/Resources/Selection.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Link } from 'react-router-dom';
3 | import './styles/Selection.css';
4 |
5 | function Selection({ match }) {
6 | var technology = ['native', 'server', 'web', 'crossPlatform', 'tooling'];
7 | return (
8 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | );
47 | }
48 |
49 | export default ReaderMenu;
50 |
--------------------------------------------------------------------------------
/src/components/ToolChain/Tooling.md:
--------------------------------------------------------------------------------
1 | ## Refmt
2 | Line-wrapping AST based formatting is an important feature of
3 | Reason that integrates with your editing experience. Reason
4 | includes a powerful, consistent syntax formatter/converter
5 | called refmt, that can parse, and print the Reason syntax at
6 | arbitrary width wrappings, while interleaving comments. It
7 | can also be used to convert between multiple syntaxes.
8 |
9 | [Documentation](/) [Guide]()
10 | ___
11 |
12 | ## Reason-tools
13 | Reason-tools is a very convenient browser extension for
14 | quickly toggling between OCaml syntax and Reason syntax.
15 | It also makes the ocaml libraries documentation pages prettier.
16 |
17 | [Guide](/) [Github](https://github.com/reasonml/reason-tools)
18 | ___
19 |
20 | ## Esy
21 | Package Management Solution for Reason libraries. Fast Installs,
22 | Instant Rebuilds, and Reliable.
23 |
24 | [Documentation](/) [Guide](/) [Github](/)
25 | ___
26 |
27 | ## Rebel
28 | A Build system that conforms to ideal Reason build spec.
29 | It can build for both Native and Web.Implemented with Jenga,
30 | and depends on bucklescript and ocamlopt when compiling.
31 |
32 | [Documentation](/) [Guide](/) [Github](/https://github.com/reasonml/rebel)
33 | ___
34 |
35 | ## Bucklescript
36 | BuckleScript is a backend for the OCaml compiler which
37 | emits JavaScript. It works with both vanilla OCaml and
38 | Reason, the whole compiler is compiled into JS (and ASM)
39 | so that you can play it in the browser.
40 |
41 | [Documentation](/) [Guide](/) [Github](/https://github.com/bloomberg/bucklescript)
42 | ___
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rdn",
3 | "version": "0.0.0",
4 | "description": "Reason Developer Network",
5 | "main": "index.js",
6 | "author": "Kennet Postigo ",
7 | "license": "MIT",
8 | "scripts": {
9 | "start": "node server.js",
10 | "build": "cross-env NODE_ENV=production webpack",
11 | "watch": "cross-env NODE_ENV=dev webpack -w",
12 | "markdown": "node ./buildMarkdown.js"
13 | },
14 | "dependencies": {
15 | "compression": "^1.6.2",
16 | "express": "^4.15.2",
17 | "node-dir": "0.1.16",
18 | "offline-plugin": "^4.6.1",
19 | "prismjs": "^1.6.0",
20 | "rad-codehighlighter": "^0.0.15",
21 | "rad-navbar": "^0.0.14",
22 | "react": "^15.4.2",
23 | "react-dom": "^15.4.2",
24 | "react-markdown": "^2.4.5",
25 | "react-router-dom": "next",
26 | "typeface-montserrat": "^0.0.24"
27 | },
28 | "devDependencies": {
29 | "babel-core": "^6.23.1",
30 | "babel-loader": "^6.3.2",
31 | "babel-plugin-syntax-dynamic-import": "^6.18.0",
32 | "babel-preset-es2015": "^6.22.0",
33 | "babel-preset-react": "^6.23.0",
34 | "babel-preset-stage-2": "^6.22.0",
35 | "copy-webpack-plugin": "^4.0.1",
36 | "cross-env": "^3.2.3",
37 | "css-loader": "^0.26.2",
38 | "extract-text-webpack-plugin": "^2.1.0",
39 | "file-loader": "^0.10.1",
40 | "html-loader": "^0.4.5",
41 | "html-webpack-plugin": "^2.28.0",
42 | "raw-loader": "^0.5.1",
43 | "react-hot-loader": "^1.3.1",
44 | "style-loader": "^0.13.2",
45 | "url-loader": "^0.5.8",
46 | "webpack": "^2.2.1"
47 | }
48 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | __Under Construction__
4 |
5 | The Reason Developer Network aims at being a resource that beginners and experienced reason developers can use as a means to learn reason and it's ecosystem or simply as a reference.
6 |
7 | ## Writing
8 | The content on RDN is divided into two categories, Documentation and Guides where Documentation is for documenting features and guides is for showing developers these features, how to use them, and how to build with them. There are some conventions to follow when writing documentation and guides:
9 |
10 | 1. Include a `tableOfContents.md` so that we can generate a menu with it.
11 |
12 | 2. Include a `meta.md` with a description of your guide/documentation.
13 |
14 | ## How to Help
15 |
16 | I developed this in my spare time but don't have enough time to finish polishing and writing content. You can help RDN in 2 ways:
17 |
18 | 1. Submit PR's for the blockers of getting RDN online, of which I have opened issues for.
19 | 2. Write documentation or guides
20 |
21 | ## Developing
22 | run:
23 | ```bash
24 | yarn
25 | ```
26 | ```bash
27 | yarn run watch
28 | ```
29 | ```bash
30 | yarn run build
31 | ```
32 | ```bash
33 | yarn run start
34 | ```
35 |
36 | To generate markdown file "map" use the following command:
37 | ```bash
38 | yarn run markdown
39 | ```
40 |
41 | If this command isn't ran when new markdown files are created then you will encounter some errors of them not being found. Just run the command when new markdown files are created.
42 |
43 |
44 | Open browser to `localhost:8000`
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/components/Reader/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import asyncMarkdown from './../Standalone/AsyncMarkdown.js';
3 | import ReaderMenu from './ReaderMenu.js';
4 | import './styles/Reader.css';
5 |
6 | function Reader(props) {
7 | if (!props.match.params.section) {
8 | var Markdown = asyncMarkdown(() =>
9 | import(`./../../../${props.match.params.category}/${props.match.params.technology}/${props.match.params.name}/${props.match.params.content}.md`)
10 | .then(module => module, err => console.log(err))
11 | );
12 | } else {
13 | var Markdown = asyncMarkdown(() =>
14 | import(`./../../../${props.match.params.category}/${props.match.params.technology}/${props.match.params.name}/${props.match.params.section}/${props.match.params.content}.md`)
15 | .then(module => module, err => console.log(err))
16 | );
17 | }
18 | return (
19 |
37 | );
38 | }
39 |
40 | export default Reader;
41 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/introduction.md:
--------------------------------------------------------------------------------
1 | # An Introduction to Reason
2 |
3 | [Reason](http://facebook.github.io/reason/) is a new frontend and developer experience built on the OCaml programming language. The goal of Reason is to harness the decades of research that went into OCaml and extend its reach to all kinds of developers.
4 |
5 | This book will:
6 |
7 | * Teach you the fundamentals of Reason
8 | * Show you how you can build applications in Reason
9 |
10 | By the end of this book hopefully you will have a solid working knowledge of Reason or a foundation to continue building on with further learning.
11 |
12 | ### Why Should I Use Reason?
13 |
14 | Reason has no limit to its reach and is not bound to any programming context. Reason can be used to build highly performant servers, systems, web, desktop, and mobile applications. To sum it up:
15 |
16 | * Developer Experience
17 | * Performance
18 | * Ubiquity Across Platforms
19 | * Phenomenal Toolchain
20 | * Applications with Small Footprints
21 |
22 | ### What type of Programming Language is Reason?
23 |
24 | Reason is a functional programming language. However it also allows you to program imperatively in order to make working with side-effects easy and natural. Reason gives you the power to embrace the best parts of imperative and functional programming paradigms to make your code as performant as possible!
25 |
26 | ### Community
27 |
28 | Reason is on a rapid trajectory growth, and the Reason community is filled with bright, kind, and welcoming people. If you have any questions or just want to talk Reason:
29 |
30 | * [Discord](https://discordapp.com/invite/reasonml)
31 | * [StackOverFlow](http://stackoverflow.com/questions/tagged/reason)
32 |
33 |
34 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/types/typeAliases.md:
--------------------------------------------------------------------------------
1 | # Type Aliases
2 |
3 | The whole point of type aliases is to make you type annotations easier to read.
4 |
5 | As your programs get more complicated, you find yourself working with larger and more complex data. For example maybe you are making twitter-for-dogs and you need to represent a user. Maybe you want a function that checks to see if a user has a bio or not. You might write a function like this:
6 |
7 | ```reason
8 | type user = {name: string, bio: string, pic: string};
9 |
10 | type hasBio = user => bool;
11 |
12 | let hasBio = fun {bio} => String.length bio > 0;
13 | ```
14 |
15 | The type annotation here are clear. There is a `user` type that is a record. Then the type for `hasBio` takes a `user` and returns a `bool`. Finally the implementation of `hasBio` which uses some pattern-matching to take the bio field off the `user` record passed in.
16 |
17 | So if we write a function to add a bio, it would be like this:
18 |
19 | ```reason
20 | type addBio = string => user => user;
21 | let addBio = fun bio user => {
22 | let user = {...user, bio: bio};
23 | };
24 | ```
25 |
26 | Imagine what the type annotation would look like if we did not have the user type alias. Bad!
27 |
28 | Type aliases are not just about cosmetics though. They can help you think more clearly. When writing Reason programs, it is often best to _start_ with the type alias before writing a bunch of functions. I find it helps direct my progress in a way that ends up being more efficient overall. Suddenly you know exactly what kind of data you are working with. If you need to add stuff to it, the compiler will tell you about any existing code that is affected by it. I think most experienced Reason folks use a similar process when working with records especially.
29 |
--------------------------------------------------------------------------------
/src/components/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
3 | import asyncComponent from './Standalone/AsyncComponent.js'
4 | import Navbar from './Standalone/Navbar.js';
5 | import './../styles';
6 |
7 | const Home = asyncComponent(() =>
8 | import('./Home')
9 | .then(module => module.default, err => console.log(err))
10 | );
11 | const Toolchain = asyncComponent(() =>
12 | import('./ToolChain')
13 | .then(module => module.default, err => console.log(err))
14 | );
15 | const Community = asyncComponent(() =>
16 | import('./Community')
17 | .then(module => module.default, err => console.log(err))
18 | );
19 | const Reader = asyncComponent(() =>
20 | import('./Reader')
21 | .then(module => module.default, err => console.log(err))
22 | );
23 | const Resources = asyncComponent(() =>
24 | import('./Resources')
25 | .then(module => module.default, err => console.log(err))
26 | );
27 |
28 | export default function App(props) {
29 | return (
30 |
31 |
32 |
33 |
34 |
35 |
36 |
41 |
46 |
51 |
52 |
53 | );
54 | }
55 |
--------------------------------------------------------------------------------
/src/components/Standalone/styles/Navbar.css:
--------------------------------------------------------------------------------
1 | .nav {
2 | background: linear-gradient(45deg, #fbfbfb, #dadada);
3 | }
4 | .nav-brand {
5 | width: 60px;
6 | height: 60px;
7 | margin-right: 20px;
8 | margin-left: -10px;
9 | }
10 | .nav-btn {
11 | background-color: #CBCBCB;
12 | color: #FFFFFF;
13 | border: none;
14 | height: 30px;
15 | width: 35px;
16 | padding: 4px;
17 | margin-bottom: 3px;
18 | border-top-right-radius: 7px;
19 | border-bottom-right-radius: 7px;
20 | }
21 | .nav-input {
22 | border-top-left-radius: 7px;
23 | border-bottom-left-radius: 7px;
24 | background-color: #fff;
25 | color: #5E5E5E;
26 | border: none;
27 | margin: 0;
28 | width: 400px;
29 | height: 20px;
30 | padding: 5px 10px;
31 | font-size: 14px;
32 | margin-top: 10px;
33 | }
34 | ::placeholder{
35 | color: #EAEAEA;
36 | }
37 | .nav-selection {
38 | display: flex;
39 | justify-content: space-between;
40 | align-items: center;
41 | padding: 0 100px;
42 | }
43 | .nav-selection a p{
44 | color: #707070;
45 | }
46 | .center {
47 | display: flex;
48 | align-items: center;
49 | justify-content: space-between;
50 | }
51 | @media(max-width: 600px) {
52 | .nav-brand {
53 | margin-right: 10px;
54 | width: 50px;
55 | height: 50px;
56 | }
57 | .nav-input {
58 | width: 300px;
59 | }
60 | .nav-selection {
61 | padding: 0 50px;
62 | }
63 | }
64 | @media(max-width: 445px) {
65 | .nav-brand {
66 | margin-right: 10px;
67 | width: 50px;
68 | height: 50px;
69 | }
70 | .nav-input {
71 | width: 250px;
72 | }
73 | .nav-selection {
74 | padding: 0 25px;
75 | }
76 | }
77 | @media(max-width: 385px) {
78 | .nav-brand {
79 | margin-right: 10px;
80 | width: 50px;
81 | height: 50px;
82 | }
83 | .nav-input {
84 | width: 200px;
85 | }
86 | .nav-selection {
87 | padding: 0 12.5px;
88 | }
89 | }
--------------------------------------------------------------------------------
/src/components/Reader/styles/Reader.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | font-size: 32px;
3 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
4 | font-weight: 400;
5 | }
6 | h2 {
7 | font-size: 28px;
8 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
9 | font-weight: 400;
10 | margin-bottom: 0px;
11 | }
12 | h3 {
13 | font-size: 24px;
14 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
15 | font-weight: 400;
16 | }
17 |
18 | h4 {
19 | font-size: 18px;
20 | margin: auto 0 0px 0;
21 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
22 | font-weight: 500;
23 | }
24 |
25 | .reader p, li {
26 | font-size: 16px !important;
27 | font-weight: 400;
28 | line-height: 1.7;
29 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
30 | margin: 20px auto;
31 | }
32 |
33 | p, li {
34 | font-size: 16px !important;
35 | font-weight: 400;
36 | line-height: 1.7;
37 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
38 | margin: 5px 0;
39 | }
40 |
41 | ul li{
42 | list-style: disc;
43 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
44 | }
45 | ol li{
46 | list-style: decimal;
47 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
48 | }
49 | code {
50 | padding: 4px;
51 | background: #f7f7f7;
52 | font-family: Consolas,"Liberation Mono",Menlo,Courier,monospace;
53 | }
54 | blockquote {
55 | margin: 0;
56 | margin-bottom: .85em;
57 | padding: 0 15px;
58 | color: #858585;
59 | border-left: 4px solid #e5e5e5;
60 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
61 | }
62 | blockquote p{
63 | color: #858585;
64 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
65 | }
66 |
67 | blockquote ul li{
68 | list-style: disc;
69 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
70 | }
71 | pre {
72 | font-size: 14px;
73 | font-family: Consolas,"Liberation Mono",Menlo,Courier,monospace;
74 | }
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/coreLanguage/tuples.md:
--------------------------------------------------------------------------------
1 | # Tuples
2 |
3 | > If you haven't read the [Core Language Overview](/reader/guides/native/anIntroductionToReason/coreLanguage/coreLanguage) please do before diving deeper.
4 |
5 | Tuples are a simple data structure that can hold a fixed number of values of any type. They are often useful for returning multiple values from a function. Lets take a look at a quick exampled of a tuple:
6 |
7 | ```reason
8 | Reason # let dbz = ("Goku", "Vegeta");
9 | let dbz : (string, string) = ("Goku", "Vegeta")
10 |
11 | Reason # let dwyaneWade = ("sg", 3);
12 | let dwyaneWade : (string, int) = ("sg", 3)
13 | ```
14 |
15 | Tuples must always be wrapped in parenthesis and are separated by commas. Lets return a tuple from a function:
16 |
17 | ```reason
18 | Reason # let tupler => (2, "tuple");
19 | let tupler : unit => (int, string) =
20 | ```
21 |
22 | How do we type our tuples? You can type tuples in 2 ways, type annotating inline or type aliasing them:
23 |
24 | ```reason
25 | Reason # let dwyaneWade : (string, int) = ("sg", 3);
26 | let dwyaneWade : (string, int) = ("sg", 3)
27 |
28 | Reason # type player = (string, int);
29 | type player = (string, int)
30 |
31 | Reason # let dwyaneWade : player = ("sg", 3);
32 | let dwyaneWade : player = ("sg", 3)
33 | ```
34 |
35 | You can generally type most things in that way. The nice part about tuples is that you can easily destructure them to pull off what you need:
36 |
37 | ```reason
38 | Reason # type player = (string, int);
39 | type player = (string, int)
40 |
41 | Reason # let dwyaneWade : player = ("sg", 3);
42 | let dwyaneWade : player = ("sg", 3)
43 |
44 | Reason # let (p, n) = dwyaneWade;
45 | let p : string = "sg"
46 | let n : int = 3
47 | ```
48 |
49 | As seen above we have assigned two variables _p_ and _n_ to the values from Dwyane Wade.Tuples are simple and should usually be used for simple use cases. Tuples are not a drop in replacement for Lists or Records.
50 |
--------------------------------------------------------------------------------
/src/components/Reader/styles/ReaderMenu.css:
--------------------------------------------------------------------------------
1 | .navdrawer p{
2 | margin-top: 0 !important;
3 | margin-bottom: 0 !important;
4 | padding-top: 0 !important;
5 | padding-bottom: 0 !important;
6 | }
7 | .reader-menu {
8 | background: #FBFBFB !important;
9 | color: #000000;
10 | }
11 | .reader-toc {
12 | margin-left: 15px;
13 | }
14 | .navdrawer {
15 | background: #FBFBFB !important;
16 | overflow: hidden;
17 | }
18 | .reader-toc h4 {
19 | font-size: 16px;
20 | font-weight: bold;
21 | text-align: center;
22 | margin: 20px 0px;
23 | color: #434343;
24 | }
25 | .reader-toc a {
26 | color: #757575;
27 | }
28 | .reader-toc p {
29 | margin: 0 0 !important;
30 | padding: 0 0 !important;
31 | }
32 | .reader-toc ul {
33 | padding: 0;
34 | margin: 0;
35 | }
36 | .reader-toc ul li{
37 | font-weight: 400;
38 | }
39 | .reader-toc ul li ul li{
40 | font-weight: 300;
41 | }
42 | .reader-toc ul li ul{
43 | margin-left: 12px;
44 | }
45 | .reader-toc li {
46 | list-style: none;
47 | }
48 | .reader-title {
49 | font-weight: bold;
50 | color: #000000;
51 | }
52 | .normalize {
53 | margin: auto;
54 | }
55 | .reader-section {
56 | font-size: 14px !important;
57 | margin-left: -40px !important;
58 | }
59 | .reader-title {
60 | font-size: 16px !important;
61 | font-weight: 500 !important;
62 | }
63 | @media(max-width: 610px) {
64 | .reader-section {
65 | font-size: 12px !important;
66 | }
67 | .reader-title {
68 | font-size: 14px !important;
69 | }
70 | }
71 | @media(max-width: 460px) {
72 | .reader-section {
73 | display: none;
74 | }
75 | .reader-title {
76 | margin-left: -40px !important;
77 | font-size: 14px !important;
78 | }
79 | }
80 | @media(max-width: 460px) {
81 | .reader-section {
82 | display: none;
83 | margin: 0 !important;
84 | }
85 | .reader-menu .navItemsright, .reader-menu .navItemsleft {
86 | display: none !important;
87 | }
88 | .reader-title {
89 | margin-left: -20px !important;
90 | font-size: 12px !important;
91 | }
92 | }
--------------------------------------------------------------------------------
/src/components/Standalone/CodeBlock.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import { Codehighlighter } from 'rad-codehighlighter';
3 | import Prism from 'prismjs';
4 | import 'prismjs/components/prism-reason.min.js';
5 | import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
6 | import './styles/CodeBlock.css';
7 |
8 | function CodeBlock(props) {
9 | return (
10 |
18 | {props.literal}
19 |
20 | );
21 | }
22 |
23 | Prism.hooks.add('complete', function(env) {
24 | if (!env.code) {
25 | return;
26 | }
27 | var pre = env.element.parentNode;
28 | var clsReg = /\s*\bline-numbers\b\s*/;
29 | if (
30 | !pre ||
31 | !/pre/i.test(pre.nodeName) ||
32 | (!clsReg.test(pre.className) && !clsReg.test(env.element.className))
33 | ) {
34 | return;
35 | }
36 |
37 | if (env.element.querySelector('.line-numbers-rows')) {
38 | return;
39 | }
40 |
41 | if (clsReg.test(env.element.className)) {
42 | env.element.className = env.element.className.replace(clsReg, '');
43 | }
44 | if (!clsReg.test(pre.className)) {
45 | pre.className += ' line-numbers';
46 | }
47 |
48 | var match = env.code.match(/\n(?!$)/g);
49 | var linesNum = match ? match.length + 1 : 1;
50 | var lineNumbersWrapper;
51 |
52 | var lines = new Array(linesNum + 1);
53 | lines = lines.join('');
54 |
55 | lineNumbersWrapper = document.createElement('span');
56 | lineNumbersWrapper.setAttribute('aria-hidden', 'true');
57 | lineNumbersWrapper.className = 'line-numbers-rows';
58 | lineNumbersWrapper.innerHTML = lines;
59 |
60 | if (pre.hasAttribute('data-start')) {
61 | pre.style.counterReset = 'linenumber ' +
62 | (parseInt(pre.getAttribute('data-start'), 10) - 1);
63 | }
64 |
65 | env.element.appendChild(lineNumbersWrapper);
66 | });
67 |
68 | export default CodeBlock;
69 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/getUpNRunning.md:
--------------------------------------------------------------------------------
1 | # Get Up & Running
2 |
3 | Getting up and running in reason is a bit different than your traditional programming language. Reason embraces sandboxed or self-contained environments for programming applications or libraries in Reason. So instead of installing reason globally on your machine and installing reason tools and editor plugins and configuring all of these yourself you use [ReasonProject](https://reasonml.github.io/ReasonProject/). It will automatically get this all setup for you.
4 |
5 | ```bash
6 | git clone https://github.com/reasonml/ReasonProject.git [ project name ]
7 | cd [ project name ]
8 | npm install
9 | ```
10 |
11 | Once you do this add the following to your **.bashrc**:
12 |
13 | ```bash
14 | //pick your editor
15 | export EDITOR=atom
16 | export EDITOR=vim
17 | export EDITOR=mvim
18 | ```
19 |
20 | Then run this command in your project directory:
21 |
22 | ```js
23 | npm run editor
24 | ```
25 |
26 | #### Refmt
27 |
28 | After you install all of this in your editor you should have `refmt` available to you. It is a powerful tool that will allow you to forget about code style and linting. It will automatically format your code to what is considered "standard" in Reason. This is great for a few reasons but most importantly that your code and another persons code will look the same, it will help readability and make it easier to understand code that is not your own. After you write some code or make changes to code type `cmd+shift+c` to format your code.
29 |
30 | From here on out you should have:
31 |
32 | * Syntax Highlighting
33 | * Auto Completion
34 | * In Editor Error Reporting
35 | * Build Tools
36 | * Code Formatting \(refmt\)
37 |
38 | If you want to have a complete list of commands and tools available to you please consult the [ReasonProject Documentation](https://reasonml.github.io/ReasonProject/)
39 |
40 | ## Reason Extension
41 |
42 | Reason is new and there aren't many resources out there written in Reason. However, because Reason is a new syntax on top of OCaml it is possible to convert OCaml to Reason. [Ricky Vetter](https://github.com/rickyvetter) created[ reason-tools](https://github.com/rickyvetter/reason-tools) for this purpose and it seamlessly converts OCaml resources \(docs, code, etc.\) into reason resources. You grab the reason-tools extension on [chrome](https://chrome.google.com/webstore/detail/reason-tools/kmdelnjbembbiodplmhgfjpecibfhadd)/[firefox](https://addons.mozilla.org/en-US/firefox/addon/reason-tools/).
43 |
--------------------------------------------------------------------------------
/src/components/Home/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 | import Card from './../Standalone/Card.js';
4 | import Edit from './../Standalone/Edit.js';
5 | import Languages from './../Standalone/Languages.js';
6 | import './styles/Home.css';
7 |
8 | function Home(props) {
9 | return (
10 |
11 |
12 |
Reason Developer Network
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Documentation
21 |
view all
22 |
23 |
24 |
25 |
26 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
27 |
28 |
29 |
30 |
31 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
32 |
33 |
34 |
35 |
36 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
37 |
38 |
39 |
40 |
41 |
42 |
Guides
43 |
view all
44 |
45 |
46 |
47 |
48 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
49 |
50 |
51 |
52 |
53 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
54 |
55 |
56 |
57 |
58 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
59 |
60 |
61 |
62 |
63 |
Talks & Slides
64 |
view all
65 |
66 |
67 |
68 |
69 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
70 |
71 |
72 |
73 |
74 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
75 |
76 |
77 |
78 |
79 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
80 |
90 | );
91 | }
92 | }
93 |
94 | export default Dropdown;
95 |
--------------------------------------------------------------------------------
/src/components/Standalone/styles/CodeBlock.css:
--------------------------------------------------------------------------------
1 | pre {
2 | border-left: 5px solid #ea7765;
3 | background: url("/assets/Grid.png") top center #fafbfc !important;
4 | }
5 | code {
6 | margin-left: 0;
7 | padding-left: 0;
8 | }
9 | code[class*="language-"],
10 | pre[class*="language-"] {
11 | color: black;
12 | background: none;
13 | text-shadow: 0 1px white;
14 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
15 | text-align: left;
16 | white-space: pre;
17 | word-spacing: normal;
18 | word-break: normal;
19 | word-wrap: normal;
20 | line-height: 1.5;
21 | font-size: 16px !important;
22 | -moz-tab-size: 4;
23 | -o-tab-size: 4;
24 | tab-size: 4;
25 | -webkit-hyphens: none;
26 | -moz-hyphens: none;
27 | -ms-hyphens: none;
28 | hyphens: none;
29 | }
30 |
31 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
32 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
33 | text-shadow: none;
34 | background: #b3d4fc;
35 | }
36 |
37 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
38 | code[class*="language-"]::selection, code[class*="language-"] ::selection {
39 | text-shadow: none;
40 | background: #b3d4fc;
41 | }
42 |
43 | @media print {
44 | code[class*="language-"],
45 | pre[class*="language-"] {
46 | text-shadow: none;
47 | }
48 | }
49 |
50 | /* Code blocks */
51 | pre[class*="language-"] {
52 | padding: 1em;
53 | margin: .5em 0;
54 | overflow: auto;
55 | }
56 |
57 | :not(pre) > code[class*="language-"],
58 | pre[class*="language-"] {
59 | background: #f5f2f0;
60 | }
61 |
62 | /* Inline code */
63 | :not(pre) > code[class*="language-"] {
64 | padding: .1em;
65 | border-radius: .3em;
66 | white-space: normal;
67 | }
68 |
69 | .token.comment,
70 | .token.prolog,
71 | .token.doctype,
72 | .token.cdata {
73 | color: slategray;
74 | }
75 |
76 | .token.punctuation {
77 | color: #999;
78 | }
79 |
80 | .namespace {
81 | opacity: .7;
82 | }
83 |
84 | .token.property,
85 | .token.tag,
86 | .token.boolean,
87 | .token.number,
88 | .token.constant,
89 | .token.symbol,
90 | .token.deleted {
91 | color: #905;
92 | }
93 |
94 | .token.selector,
95 | .token.attr-name,
96 | .token.string,
97 | .token.char,
98 | .token.builtin,
99 | .token.inserted {
100 | color: #690;
101 | }
102 |
103 | .token.operator,
104 | .token.entity,
105 | .token.url,
106 | .language-css .token.string,
107 | .style .token.string {
108 | color: #a67f59;
109 | background: hsla(0, 0%, 100%, .5);
110 | }
111 |
112 | .token.atrule,
113 | .token.attr-value,
114 | .token.keyword {
115 | color: #07a;
116 | }
117 |
118 | .token.function {
119 | color: #DD4A68;
120 | }
121 |
122 | .token.regex,
123 | .token.important,
124 | .token.variable {
125 | color: #e90;
126 | }
127 |
128 | .token.important,
129 | .token.bold {
130 | font-weight: bold;
131 | }
132 | .token.italic {
133 | font-style: italic;
134 | }
135 | .token.entity {
136 | cursor: help;
137 | }
138 |
139 | pre.line-numbers {
140 | position: relative;
141 | padding-left: 3.8em;
142 | counter-reset: linenumber;
143 | }
144 |
145 | pre.line-numbers > code {
146 | position: relative;
147 | }
148 |
149 | .line-numbers .line-numbers-rows {
150 | position: absolute;
151 | pointer-events: none;
152 | top: 0;
153 | font-size: 100%;
154 | left: -3.8em;
155 | width: 3em; /* works for line-numbers below 1000 lines */
156 | letter-spacing: -1px;
157 | border-right: 1px solid #999;
158 |
159 | -webkit-user-select: none;
160 | -moz-user-select: none;
161 | -ms-user-select: none;
162 | user-select: none;
163 |
164 | }
165 |
166 | .line-numbers-rows > span {
167 | pointer-events: none;
168 | display: block;
169 | counter-increment: linenumber;
170 | }
171 |
172 | .line-numbers-rows > span:before {
173 | content: counter(linenumber);
174 | color: #999;
175 | display: block;
176 | padding-right: 0.8em;
177 | text-align: right;
178 | }
--------------------------------------------------------------------------------
/src/swm.js:
--------------------------------------------------------------------------------
1 | var mdpath = [
2 | "documentation/native/reason/array/append.md",
3 | "documentation/native/reason/array/array.md",
4 | "documentation/native/reason/array/blit.md",
5 | "documentation/native/reason/array/concat.md",
6 | "documentation/native/reason/array/copy.md",
7 | "documentation/native/reason/array/create_float.md",
8 | "documentation/native/reason/array/fill.md",
9 | "documentation/native/reason/array/get.md",
10 | "documentation/native/reason/array/init.md",
11 | "documentation/native/reason/array/length.md",
12 | "documentation/native/reason/array/make.md",
13 | "documentation/native/reason/array/make_matrix.md",
14 | "documentation/native/reason/array/of_list.md",
15 | "documentation/native/reason/array/set.md",
16 | "documentation/native/reason/array/sub.md",
17 | "documentation/native/reason/array/to_list.md",
18 | "documentation/native/reason/introduction.md",
19 | "documentation/native/reason/list/append.md",
20 | "documentation/native/reason/list/concat.md",
21 | "documentation/native/reason/list/cons.md",
22 | "documentation/native/reason/list/flatten.md",
23 | "documentation/native/reason/list/hd.md",
24 | "documentation/native/reason/list/length.md",
25 | "documentation/native/reason/list/list.md",
26 | "documentation/native/reason/list/nth.md",
27 | "documentation/native/reason/list/rev.md",
28 | "documentation/native/reason/list/rev_append.md",
29 | "documentation/native/reason/list/tl.md",
30 | "documentation/native/reason/meta.md",
31 | "documentation/native/reason/string/capitalize.md",
32 | "documentation/native/reason/string/capitalize_ascii.md",
33 | "documentation/native/reason/string/compare.md",
34 | "documentation/native/reason/string/concat.md",
35 | "documentation/native/reason/string/contains.md",
36 | "documentation/native/reason/string/contains_from.md",
37 | "documentation/native/reason/string/equal.md",
38 | "documentation/native/reason/string/escaped.md",
39 | "documentation/native/reason/string/get.md",
40 | "documentation/native/reason/string/index.md",
41 | "documentation/native/reason/string/index_from.md",
42 | "documentation/native/reason/string/init.md",
43 | "documentation/native/reason/string/iter.md",
44 | "documentation/native/reason/string/iteri.md",
45 | "documentation/native/reason/string/length.md",
46 | "documentation/native/reason/string/lowercase.md",
47 | "documentation/native/reason/string/lowercase_ascii.md",
48 | "documentation/native/reason/string/make.md",
49 | "documentation/native/reason/string/map.md",
50 | "documentation/native/reason/string/mapi.md",
51 | "documentation/native/reason/string/rcontains_from.md",
52 | "documentation/native/reason/string/rindex.md",
53 | "documentation/native/reason/string/rindex_from.md",
54 | "documentation/native/reason/string/split_on_char.md",
55 | "documentation/native/reason/string/string.md",
56 | "documentation/native/reason/string/sub.md",
57 | "documentation/native/reason/string/trim.md",
58 | "documentation/native/reason/string/uncapitalize.md",
59 | "documentation/native/reason/string/uncapitalize_ascii.md",
60 | "documentation/native/reason/string/uppercase.md",
61 | "documentation/native/reason/string/uppercase_ascii.md",
62 | "documentation/native/reason/tableOfContents.md",
63 | "guides/native/anIntroductionToReason/coreLanguage/coreLanguage.md",
64 | "guides/native/anIntroductionToReason/coreLanguage/functions.md",
65 | "guides/native/anIntroductionToReason/coreLanguage/functors.md",
66 | "guides/native/anIntroductionToReason/coreLanguage/lists.md",
67 | "guides/native/anIntroductionToReason/coreLanguage/modules.md",
68 | "guides/native/anIntroductionToReason/coreLanguage/objects.md",
69 | "guides/native/anIntroductionToReason/coreLanguage/records.md",
70 | "guides/native/anIntroductionToReason/coreLanguage/tuples.md",
71 | "guides/native/anIntroductionToReason/getUpNRunning.md",
72 | "guides/native/anIntroductionToReason/introduction.md",
73 | "guides/native/anIntroductionToReason/meta.md",
74 | "guides/native/anIntroductionToReason/tableOfContents.md",
75 | "guides/native/anIntroductionToReason/types/readingTypes.md",
76 | "guides/native/anIntroductionToReason/types/typeAliases.md",
77 | "guides/native/anIntroductionToReason/types/types.md",
78 | "guides/native/anIntroductionToReason/types/variants.md"
79 | ];
80 | exports.markdown = mdpath
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
4 | const CopyWebpackPlugin = require('copy-webpack-plugin');
5 | const HtmlWebpackPlugin = require('html-webpack-plugin');
6 | const OfflinePlugin = require('offline-plugin');
7 | const markdown = require('./src/swm.js');
8 |
9 | const ENV = process.env.NODE_ENV || 'development';
10 |
11 | let config = {
12 | context: path.resolve(__dirname, 'src'),
13 | entry: {
14 | main: './index.js',
15 | vendor: [
16 | 'react',
17 | 'react-dom',
18 | 'react-router-dom',
19 | 'react-markdown',
20 | 'rad-codehighlighter',
21 | 'rad-navbar',
22 | 'prismjs',
23 | 'typeface-montserrat'
24 | ]
25 | },
26 | output: {
27 | path: path.resolve(__dirname, 'dist'),
28 | publicPath: '/',
29 | filename: '[name].js',
30 | chunkFilename: '[name].chunk.js'
31 | },
32 | devtool: ENV === 'production' ? 'source-map' : 'cheap-module-eval-source-map',
33 | stats: {
34 | colors: true
35 | },
36 | module: {
37 | rules: [
38 | {
39 | test: /\.js$/,
40 | use: ['babel-loader'],
41 | exclude: /node_modules/
42 | },
43 | {
44 | test: /\.css$/,
45 | use: ExtractTextPlugin.extract({
46 | fallback: 'style-loader',
47 | use: 'css-loader'
48 | })
49 | },
50 | {
51 | test: /\.html$/,
52 | use: [
53 | {
54 | loader: 'html-loader'
55 | }
56 | ]
57 | },
58 | {
59 | test: /\.md$/,
60 | use: ['raw-loader']
61 | },
62 | {
63 | test: /\.png$/,
64 | use: ['url-loader']
65 | },
66 | {
67 | test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
68 | use: ['file-loader']
69 | },
70 | {
71 | test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
72 | use: ['file-loader']
73 | }
74 | ]
75 | },
76 | plugins: [
77 | new webpack.HotModuleReplacementPlugin(),
78 | new webpack.NamedModulesPlugin(),
79 | new webpack.NoEmitOnErrorsPlugin(),
80 | new ExtractTextPlugin({ filename: '[name].css', allChunks: true }),
81 | new HtmlWebpackPlugin({
82 | template: path.resolve(__dirname + '/src/index.html'),
83 | minify: {
84 | collapseWhitespace: true,
85 | removeComments: true
86 | },
87 | title: 'RDN'
88 | }),
89 | new CopyWebpackPlugin([
90 | { from: 'manifest.json' },
91 | { from: 'assets', to: 'assets' }
92 | ]),
93 | new webpack.DefinePlugin({
94 | process: {},
95 | 'process.env': {},
96 | 'process.env.NODE_ENV': JSON.stringify(ENV)
97 | }),
98 | new webpack.optimize.CommonsChunkPlugin({
99 | name: 'vendor',
100 | minChunks: Infinity,
101 | children: true,
102 | async: false,
103 | filename: 'vendor.js'
104 | })
105 | ].concat(
106 | ENV === 'production'
107 | ? [
108 | new OfflinePlugin({
109 | version: '[hash]',
110 | responseStrategy: 'cache-first',
111 | safeToUseOptionalCaches: true,
112 | caches: {
113 | main: [
114 | 'index.html',
115 | 'vendor.js',
116 | 'main.js',
117 | 'vendor.css',
118 | 'main.css'
119 | ],
120 | additional: ['*.chunk.js', ':externals:'],
121 | optional: [':rest:']
122 | },
123 | externals: markdown.markdown,
124 | cacheMaps: [
125 | {
126 | match: /.*/,
127 | to: '/',
128 | requestTypes: ['navigate']
129 | }
130 | ],
131 | ServiceWorker: {
132 | events: true
133 | },
134 | AppCache: {
135 | FALLBACK: { '/': '/' }
136 | }
137 | }),
138 | new webpack.LoaderOptionsPlugin({
139 | minimize: true,
140 | debug: false
141 | }),
142 | new webpack.optimize.UglifyJsPlugin({
143 | beautify: false,
144 | mangle: true,
145 | compress: {
146 | screw_ie8: true
147 | },
148 | comments: false
149 | })
150 | ]
151 | : []
152 | )
153 | };
154 |
155 | module.exports = config;
156 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/coreLanguage/functors.md:
--------------------------------------------------------------------------------
1 | # Functors
2 |
3 | > If you haven't read the [Core Language Overview](/reader/guides/native/anIntroductionToReason/coreLanguage/coreLanguage) please do before diving deeper.
4 |
5 | Module Functions are commonly referred to as Functors in the OCaml Reason Community. Functors are special functions that can operate on modules. They give you the power to pass modules and signatures through functions to extend the behavior of modules, help structure your code better, and instantiate modules with state and more!
6 |
7 | Lets take a look at usage of functors:
8 |
9 | ```reason
10 | Reason # module type Car = {
11 | type y = int;
12 | type m = string;
13 | let year: y;
14 | let make: m;
15 | };
16 | module type Car =
17 | { type y = int; type m = string; let year : y; let make : m; }
18 |
19 | Reason # module SpeedRacin = fun (C: Car) => {
20 | type whip = {year: C.y, make: C.m};
21 | let myWhip = {year: C.year, make: C.make};
22 | let drive (w: whip) =>
23 | "Pull off the lot in my " ^ string_of_int w.year ^ " " ^ w.make ^ " Speed Racin!";
24 | };
25 | module SpeedRacin :
26 | (C : Car) => {
27 | type whip = { year : year, make : make, };
28 | let myWhip : whip;
29 | let drive : whip => make;
30 | }
31 | ```
32 |
33 | What we've done is first define a module signature `Car` so that we can use it when typing the module parameter of the functor `SpeedRacin` . In the `SpeedRacin` module function/functor there should be a few things that stand out to you. First that we bind the function to `module` rather than `let`. Second that we distinguish `SpeedRacin` as functor vs a regular module by using the `fun` keyword. Within the body of the functor we define the `whip` record type and the record value `myWhip` both which depend on types and values from the `C` parameter passed in. Finally we finish the functor off by defining the `drive` function that will output a string with the values of a record of type `whip` .
34 |
35 | Now lets see the functor in action:
36 |
37 | ```reason
38 | Reason # module Honda1996 = {
39 | type y = int;
40 | type m = string;
41 | let year = 1996;
42 | let make = "Honda";
43 | };
44 | module Honda1996 :
45 | { type y = year; type m = make; let year : y; let make : m; }
46 |
47 |
48 | Reason # module HondaGoVroom = SpeedRacin Honda1996;
49 | module HondaGoVroom :
50 | {
51 | type whip = SpeedRacin(Honda1996).whip = { year : year, make : make, };
52 | let myWhip : whip;
53 | let drive : whip => make;
54 | }
55 |
56 |
57 | Reason # let speedinOffInWhat = HondaGoVroom.drive HondaGoVroom.myWhip;
58 | let speedinOffInWhat : make = "Pull off the lot in my 1996 Honda Speed Racin!"
59 | ```
60 |
61 | Before we put the functor to use, lets define module `Honda1996` so that we can pass it to the functor as a parameter. `Honda1996` seems to implement the `Car` signature but we don't type it explicitly when defining it. Now, lets use the functor! We're going to define a module `HondaGoVroom` that is going to be set to the module that our `SpeedRacin` functor returns. We pass `SpeedRacin` our `Honda1996` module which from the definition of `SpeedRacin` must implement the `Car` signature. This is because we set the parameter type to `Car` it will constrain the parameter to the `Car`'s signature. After we run the code we are returned a module from the functor that is bound to `HondaGoVroom` .
62 |
63 | Lastly, we invoke the `HondaGoVroom.drive` function and pass it the `HondaGoVroom.myWhip` record, and it will successfully output `"Pull off the lot in my 1996 Honda Speed Racin!"` and bind it to `speedinOffInWhat` variable.
64 |
65 | Just like that, we're using functors! Since functors return modules can we type them as well? The answer is yes! We do it the same way we constrain regular modules:
66 |
67 | ```reason
68 | Reason # module type Car = {
69 | type y = int;
70 | type m = string;
71 | let year: y;
72 | let make: m;
73 | };
74 | module type Car =
75 | { type y = int; type m = string; let year : y; let make : m; }
76 |
77 |
78 | Reason # module type Racin = (SpeedRacinCar: Car) => {
79 | type whip = {year: SpeedRacinCar.y, make: SpeedRacinCar.m};
80 | let myWhip: whip;
81 | let drive: whip => string;
82 | };
83 | module type Racin =
84 | (SpeedRacinCar : Car) => {
85 | type whip = { year : int, make : string, };
86 | let myWhip : whip;
87 | let drive : whip => string;
88 | }
89 |
90 |
91 | Reason # module SpeedRacin: Racin = fun (C: Car) => {
92 | type whip = {year: C.y, make: C.m};
93 | let myWhip = {year: C.year, make: C.make};
94 | let drive (w: whip) =>
95 | "Pull of the lot in my " ^ string_of_int w.year ^ " " ^ w.make ^ " Speed Racin!";
96 | };
97 | module SpeedRacin : Racin
98 | ```
99 |
100 | This should look familiar to you! The only difference is that we assert the `Racin` type on the functor just like we would on modules `module SpeedRacin: Racin`.
101 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/coreLanguage/lists.md:
--------------------------------------------------------------------------------
1 | # Lists
2 |
3 | > If you haven't read the [Core Language Overview](/reader/guides/native/anIntroductionToReason/coreLanguage/coreLanguage) please do before diving deeper.
4 |
5 | Lists in reason are immutable singly lists. If you come from a Javascript background they should look familiar to you and feel natural to use. Lists have a great range of helpful built in methods that are useful for traversing, scanning, and manipulating lists. Lets dive in:
6 |
7 | ```reason
8 | Reason # let numbers = [1, 2, 3];
9 | let numbers : list int = [1, 2, 3]
10 | ```
11 |
12 | Some things to keep in mind are that lists can only hold values of the same type. You cannot mix different types together in a list. Lets take a look at this:
13 |
14 | ```reason
15 | Reason # let mixed = [1, "one", 2, "two", 3, "three"];
16 | Error: This expression has type string but an expression was expected of type
17 | int
18 | ```
19 |
20 | Reason will make you aware of the error immediately because it infers the type the list should be.
21 |
22 | Combining and appending elements to a list in Reason is different to how it is done in most languages because there is no dedicated method on List for this operation.
23 |
24 | ```reason
25 | Reason # let number = 5;
26 | let number : int = 5
27 |
28 | Reason # let numbers = [4, 3, 2, 1];
29 | let numbers : list int = [4, 3, 2, 1]
30 |
31 | Reason # let numbers = [number, ...numbers];
32 | let numbers : list int = [5, 4, 3, 2, 1]
33 | ```
34 |
35 | The `...numbers` is similar to JavaScripts spread but not quite the same. If it we're the following would be valid:
36 |
37 | ```reason
38 | Reason # let number = 5;
39 | let number : int = 5
40 |
41 | Reason # let numbers = [1, 2, 3, 4];
42 | let numbers : list int = [1, 2, 3, 4]
43 |
44 | Reason # let numbers = [...numbers, number];
45 | Error: Syntax error
46 | ```
47 |
48 | This is because `...` is the `cons` operator from OCaml under the hood and the `cons` operator expects an element to the left because it should always come after some initial element. Also you should keep in mind that appending to the end of a list is an anti pattern because it requires a full copy of the list. Adding an element to the front of the list requires allocating a single cell, whereas the tail of the new list can just point to the old list. OCaml community is ruthlessly hell bent on performance and for good reason \(is that a pun?\). If you want to accomplish this sort of task you can do the following:
49 |
50 | ```reason
51 | Reason # let number = 5;
52 | let number : int = 5
53 |
54 | Reason # let numbers = [1, 2, 3, 4];
55 | let numbers : list int = [1, 2, 3, 4]
56 |
57 | Reason # numbers @ [number];
58 | - : list int = [1, 2, 3, 4, 5]
59 | ```
60 |
61 | #### Useful List Operations
62 |
63 | You can get the length of a list by using the `length` operator:
64 |
65 | ```reason
66 | Reason # let numbers = [1, 2, 3, 4, 5];
67 | let numbers : list int = [1, 2, 3, 4, 5]
68 |
69 | Reason # List.length numbers;
70 | - : int = 5
71 | ```
72 |
73 | To grab a specific element in a list you can use the `nth` operator:
74 |
75 | ```reason
76 | Reason # let numbers = [1, 2, 3, 4, 5];
77 | let numbers : list int = [1, 2, 3, 4, 5]
78 |
79 | Reason # List.nth numbers 2;
80 | - : int = 3
81 | ```
82 |
83 | Keep in mind that you pass in the index you want and lists start at 0.
84 |
85 | You can iterate and apply transformations of elements from a list with map:
86 |
87 | ```reason
88 | Reason # let numbers = [1, 2, 3, 4, 5];
89 | let numbers : list int = [1, 2, 3, 4, 5]
90 |
91 | Reason # List.map (fun n => n + 1) numbers;
92 | - : list int = [2, 3, 4, 5, 6]
93 | ```
94 |
95 | If you want to process a list in order to build a return value than `fold_left` and `fold_right` are the tools for the job. If you come from a JavaScript background then `fold_left` is `reduce` and `fold_right` is `reduceRight` . Lets take a look at both:
96 |
97 | ```reason
98 | Reason # List.fold_left (fun a b => a + b) 0 numbers;
99 | - : int = 15
100 |
101 | Reason # List.fold_right (fun a b => a + b) numbers 0;
102 | - : int = 15
103 | ```
104 |
105 | They both provide the same result in this scenario but not always. There is a subtle difference between the order in which the lists is being processed:
106 |
107 | ```reason
108 | // fold_left
109 | (((((0 + 1) + 2) + 3) + 4) + 5)
110 |
111 | fold_right
112 | (1 + (2 + (3 + (4 + (5 + 0)))))
113 | ```
114 |
115 | There are a lot more operators we won't cover here, but you can find them in the [List module](http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html) of the OCaml documentation.
116 |
117 | ## Similar Data Structures
118 |
119 | Reason has similar list like data structures that you can use. Array is one alternative to List but using Array over List and vice versa has their own tradeoffs. Heres a simple example of what Arrays look like in Reason:
120 |
121 | ```reason
122 | Reason # [| 1, 2, 3 |];
123 | - : array int = [|1, 2, 3|]
124 | ```
125 |
126 |
127 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/coreLanguage/records.md:
--------------------------------------------------------------------------------
1 | # Records
2 |
3 | > If you haven't read the [Core Language Overview](/reader/guides/native/anIntroductionToReason/coreLanguage/coreLanguage) please do before diving deeper.
4 |
5 | Records in Reason are the go-to `key:value` data structure you should use when ever the need for it arises. They are similar to Objects in Javascript and Dictionaries in Python with a few differences.
6 |
7 | Before using a record you must make sure do define the shape the record will take:
8 |
9 | ```reason
10 | Reason # type hero = {name: string, power: string, age: int};
11 | type hero = { name : string, power : string, age : int, }
12 | ```
13 |
14 | Once you've got that done you can now go ahead and start creating records that implement the definition above.
15 |
16 | ```reason
17 | Reason # let superman = {name: "superman", power: "everything that matters", age: 35};
18 | let superman : hero =
19 | {name : "superman", power : "everything that matters", age : 35}
20 |
21 | Reason # let flash = {name: "flash", power: "super speed", age: 25};
22 | let flash : hero = {name : "flash", power : "super speed", age : 25}
23 | ```
24 |
25 | What happens if we don't follow the type definition of the record?
26 |
27 | ```reason
28 | Reason # let aquaman = {name: "aquaman", age: 50};
29 | Error: Some record fields are undefined: power
30 |
31 | Reason # let aquaman = {name: "aquaman", power: "power?", age: 50, marvelMovie: false};
32 | Error: Unbound record field marvelMovie
33 | ```
34 |
35 | Well Reason loses its mind! Nah, it just lets you know that you aren't following the type definition and the proceeds to list the fields that violate the type definition. Pretty neat huh?
36 |
37 | #### Updating Record Fields
38 |
39 | Records in Reason are special when it comes to updating fields. You can do this in 2 ways, immutable updates and mutable updates.
40 |
41 | ```reason
42 | Reason # type person = {name: string, age: int};
43 | type person = { name : string, age : int, }
44 |
45 | Reason # let bob = {name: "bob", age: 22};
46 | let bob : person = {name : "bob", age : 22}
47 |
48 | Reason # let birthday person => {...person, age: person.age + 1};
49 | let birthday : person => person =
50 |
51 | Reason # let bob = birthday bob;
52 | let bob : person = {name : "bob", age : 23}
53 | ```
54 |
55 | Here we are defined a `person` type, and created a variable called `bob` that is of type `person`. Then create a function called `birthday` that takes a `person` record and creates a new record with the age incremented. You must be wondering what the `{...person}` piece of code is doing, that is called destructuring, it is a technique that is used to extract one or more fields from record. So in this case the `...person` is extracting the `name` field off of the `person` record and being placed on the record returned from the `birthday` function.
56 |
57 | The second way to update a field on a record is to mark that field `mutable` on the `person` type definition. Lets update the type definition and show it in action:
58 |
59 | ```reason
60 | Reason # type person = {name: string, mutable age: int};
61 | type person = { name : string, mutable age : int, }
62 |
63 | Reason # let bob = {name: "bob", age: 22};
64 | let bob : person = {name : "bob", age : 22}
65 |
66 | Reason # let birthday person => person.age = person.age + 1;
67 | let birthday : person => unit =
68 |
69 | Reason # birthday bob;
70 | - : unit = ()
71 |
72 | Reason # bob;
73 | - : person = {name : "bob", age : 23}
74 | ```
75 |
76 | Once you update the type definition to and mark `age` field with the `mutable` keyword you can freely update the `age` field on `bob` . Now we simply just reassign the `person.age` and set it equal to `person.age + 1` in the `birthday` function and it will mutate the `bob` record directly.
77 |
78 | #### Record Field Punning
79 |
80 | In reason if you are creating a record with values that already exist and the variable name matches the record field you don't need to give the field a label and value, just the label. Lets take a look at how we would Traditionally create a record and then lets show the same example with field punning
81 |
82 | ```reason
83 | // Without Punning
84 | Reason # let name = "John Doe";
85 | let name : string = "John Doe"
86 |
87 | Reason # let basicPerson = {name: name, age: 21};
88 | let basicPerson : person = {name : "John Doe", age : 21}
89 |
90 | //With Punning
91 | Reason # let name = "John Doe";
92 | let name : string = "John Doe"
93 |
94 | Reason # let basicPerson = { name, age: 21};
95 | let basicPerson : person = {name : "John Doe", age : 21}
96 | ```
97 |
98 | The difference is subtle `name: name` vs `name` , you can choose whichever style you prefer they both have the same end result.
99 |
100 | #### Record Destructuring
101 |
102 | You can destructure one or many fields from a record and bind them to a variables.
103 |
104 | ```reason
105 | Reason # type player = {position: string, number: int};
106 | type player = { position : bytes, number : int, }
107 |
108 | Reason # let dwyaneWade : player = {position: "sg", number: 3};
109 | let dwyaneWade : player = {position : "sg", number : 3}
110 |
111 | Reason # let {position: p, number: n} = dwyaneWade;
112 | let p : bytes = "sg"
113 | let n : int = 3
114 | ```
115 |
116 |
117 |
--------------------------------------------------------------------------------
/src/markdown.js:
--------------------------------------------------------------------------------
1 | var mdpath = {
2 | "guides": {
3 | "crossPlatform": {},
4 | "native": {
5 | "anIntroductionToReason": {
6 | "coreLanguage": "guides/native/anIntroductionToReason/coreLanguage/coreLanguage.md",
7 | "functions": "guides/native/anIntroductionToReason/coreLanguage/functions.md",
8 | "functors": "guides/native/anIntroductionToReason/coreLanguage/functors.md",
9 | "lists": "guides/native/anIntroductionToReason/coreLanguage/lists.md",
10 | "modules": "guides/native/anIntroductionToReason/coreLanguage/modules.md",
11 | "objects": "guides/native/anIntroductionToReason/coreLanguage/objects.md",
12 | "records": "guides/native/anIntroductionToReason/coreLanguage/records.md",
13 | "tuples": "guides/native/anIntroductionToReason/coreLanguage/tuples.md",
14 | "getUpNRunning": "guides/native/anIntroductionToReason/getUpNRunning.md",
15 | "introduction": "guides/native/anIntroductionToReason/introduction.md",
16 | "meta": "guides/native/anIntroductionToReason/meta.md",
17 | "tableOfContents": "guides/native/anIntroductionToReason/tableOfContents.md",
18 | "readingTypes": "guides/native/anIntroductionToReason/types/readingTypes.md",
19 | "typeAliases": "guides/native/anIntroductionToReason/types/typeAliases.md",
20 | "types": "guides/native/anIntroductionToReason/types/types.md",
21 | "variants": "guides/native/anIntroductionToReason/types/variants.md"
22 | }
23 | },
24 | "server": {},
25 | "tooling": {},
26 | "web": {}
27 | },
28 | "documentation": {
29 | "crossPlatform": {},
30 | "native": {
31 | "reason": {
32 | "append": "documentation/native/reason/list/append.md",
33 | "array": "documentation/native/reason/array/array.md",
34 | "blit": "documentation/native/reason/array/blit.md",
35 | "concat": "documentation/native/reason/string/concat.md",
36 | "copy": "documentation/native/reason/array/copy.md",
37 | "create_float": "documentation/native/reason/array/create_float.md",
38 | "fill": "documentation/native/reason/array/fill.md",
39 | "get": "documentation/native/reason/string/get.md",
40 | "init": "documentation/native/reason/string/init.md",
41 | "length": "documentation/native/reason/string/length.md",
42 | "make": "documentation/native/reason/string/make.md",
43 | "make_matrix": "documentation/native/reason/array/make_matrix.md",
44 | "of_list": "documentation/native/reason/array/of_list.md",
45 | "set": "documentation/native/reason/array/set.md",
46 | "sub": "documentation/native/reason/string/sub.md",
47 | "to_list": "documentation/native/reason/array/to_list.md",
48 | "introduction": "documentation/native/reason/introduction.md",
49 | "cons": "documentation/native/reason/list/cons.md",
50 | "flatten": "documentation/native/reason/list/flatten.md",
51 | "hd": "documentation/native/reason/list/hd.md",
52 | "list": "documentation/native/reason/list/list.md",
53 | "nth": "documentation/native/reason/list/nth.md",
54 | "rev": "documentation/native/reason/list/rev.md",
55 | "rev_append": "documentation/native/reason/list/rev_append.md",
56 | "tl": "documentation/native/reason/list/tl.md",
57 | "meta": "documentation/native/reason/meta.md",
58 | "capitalize": "documentation/native/reason/string/capitalize.md",
59 | "capitalize_ascii": "documentation/native/reason/string/capitalize_ascii.md",
60 | "compare": "documentation/native/reason/string/compare.md",
61 | "contains": "documentation/native/reason/string/contains.md",
62 | "contains_from": "documentation/native/reason/string/contains_from.md",
63 | "equal": "documentation/native/reason/string/equal.md",
64 | "escaped": "documentation/native/reason/string/escaped.md",
65 | "index": "documentation/native/reason/string/index.md",
66 | "index_from": "documentation/native/reason/string/index_from.md",
67 | "iter": "documentation/native/reason/string/iter.md",
68 | "iteri": "documentation/native/reason/string/iteri.md",
69 | "lowercase": "documentation/native/reason/string/lowercase.md",
70 | "lowercase_ascii": "documentation/native/reason/string/lowercase_ascii.md",
71 | "map": "documentation/native/reason/string/map.md",
72 | "mapi": "documentation/native/reason/string/mapi.md",
73 | "rcontains_from": "documentation/native/reason/string/rcontains_from.md",
74 | "rindex": "documentation/native/reason/string/rindex.md",
75 | "rindex_from": "documentation/native/reason/string/rindex_from.md",
76 | "split_on_char": "documentation/native/reason/string/split_on_char.md",
77 | "string": "documentation/native/reason/string/string.md",
78 | "trim": "documentation/native/reason/string/trim.md",
79 | "uncapitalize": "documentation/native/reason/string/uncapitalize.md",
80 | "uncapitalize_ascii": "documentation/native/reason/string/uncapitalize_ascii.md",
81 | "uppercase": "documentation/native/reason/string/uppercase.md",
82 | "uppercase_ascii": "documentation/native/reason/string/uppercase_ascii.md",
83 | "tableOfContents": "documentation/native/reason/tableOfContents.md"
84 | }
85 | },
86 | "server": {},
87 | "tooling": {},
88 | "web": {}
89 | },
90 | "talksAndSlides": {
91 | "crossPlatform": {},
92 | "native": {},
93 | "server": {},
94 | "tooling": {},
95 | "web": {}
96 | }
97 | };
98 | export default mdpath
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/coreLanguage/functions.md:
--------------------------------------------------------------------------------
1 | # Functions
2 |
3 | > If you haven't read the [Core Language Overview](/reader/guides/native/anIntroductionToReason/coreLanguage/coreLanguage) please do before diving deeper.
4 |
5 | Functions are the smallest unit you have to build with. Many large systems are built on several small units, that are often functions. Functions are your friend!
6 |
7 | ## Anonymous Functions
8 |
9 | In reason you are able to create anonymous functions or lambdas and use them throughout your code.
10 |
11 | ```reason
12 | Reason # fun (x) => x + 10;
13 | - : int => int =
14 |
15 | Reason # fun x => x + 10;
16 | - : int => int =
17 | ```
18 |
19 | As you can see when writing functions you can choose to omit the parenthesis around the parameters you pass into the function. Both of the functions above are equivalent, even their typing is the same `- : int => int = ` . However how do we invoke these functions if they have no name?!?! Well, lets do just that:
20 |
21 | ```reason
22 | Reason # (fun (x) => x + 10)(2);
23 | - : int = 12
24 |
25 | Reason # (fun x => x + 10) 2;
26 | - : int = 12
27 | ```
28 |
29 | First thing you do is wrap the function expression in a set of parenthesis and then pass in the parameters the lambda takes. Just like with the parameters you can invoke the function with or without parenthesis.
30 |
31 | ## Named Functions
32 |
33 | Functions in reason are first class citizens! You can treat them as values in your programs and use let bindings to give them names just as you would with integers, floats, strings, etc.
34 |
35 | ```reason
36 | Reason # let add10 (n) => n + 10;
37 | let add10 : int => int =
38 |
39 | Reason # let add10 n => n + 10;
40 | let add10 : int => int =
41 | ```
42 |
43 | The function declarations above are given the name `add10`. Both are the equivalent, one doesn't use parenthesis when defining the parameters it takes.Now to invoke these functions we simply type the name of the function followed by the parameters \(with or without parenthesis\).
44 |
45 | ```reason
46 | Reason # add10(5);
47 | - : int = 15
48 |
49 | Reason # add10 5;
50 | - : int = 15
51 | ```
52 |
53 | ## Multiargument Functions & Gotchas
54 |
55 | Lets define some functions that take more than one argument:
56 |
57 | ```reason
58 | Reason # let add x y => x + y;
59 | let add : int => int => int =
60 |
61 | Reason # let add (x, y) => x + y;
62 | let add : (int, int) => int =
63 | ```
64 |
65 | Notice something odd here? The type definitions aren't the same. Meaning these function aren't really the same. Lets test them out one by one and see what problems we come across:
66 |
67 | ```reason
68 | Reason # let add (x, y) => x + y;
69 | let add : (int, int) => int =
70 |
71 | Reason # add(5,5);
72 | - : int = 10
73 |
74 | Reason # add 5 5;
75 | Error: This function has type (int, int) => int
76 | It is applied to too many arguments; maybe you forgot a `;'.
77 | ```
78 |
79 | First we define the function `add` in the REPL, notice we used the version with the parentheses around the parameters. Then we invoke the function with parentheses. The call to `add` returns 10, as we would expect. However when we invoke it again this time without parentheses we get an error complaining about the types passed in. The reason that this happens is that when you define a function with 2 or more parameters and you wrap them in parenthesis it interprets it as a function that takes a [`tuple`](/Core Language/Tuples.md) containing 2 or more values. When you call it without parenthesis you are passing 2 values of type `int`, but the function is expecting 1 `tuple` value.
80 |
81 | ```reason
82 | Reason # let add x y => x + y;
83 | let add : int => int => int =
84 |
85 | Reason # add 5 5;
86 | - : int = 10
87 |
88 | Reason # add (5, 5);
89 | Error: This expression has type ('a, 'b)
90 | but an expression was expected of type int
91 | ```
92 |
93 | The same thing can happens in reverse, this time we don't use parenthesis for the `add` parameters, and when we invoke the function without parenthesis it works out well! However when we use parenthesis to invoke the function we get an error complaining that we we didn't pass in an `int` , rather a `tuple` . So be aware of how you define your functions so that you invoke them correctly. Most times the compiler will catch it for you ahead of time and warn you.
94 |
95 | ## Labelled Arguments
96 |
97 | In many programming languages like Javascript, Java, C++, etc. argument to a function are passed in positionally. Let's illustrate what this means by creating a function that _must_ takes in a boolean then a string:
98 |
99 | ```reason
100 | Reason # let boolString (b:bool) (s:string) => (b, s);
101 | let boolString : bool => string => (bool, string) =
102 |
103 | Reason # boolString true "word up";
104 | - : (bool, string) = (true, "word up")
105 |
106 | Reason # boolString "word up" true;
107 | Error: This expression has type bytes but an expression was expected of type
108 | bool
109 | ```
110 |
111 | As you can see when we invoke `boolString` the first time with the arguments in the correct order everything goes according to plan. For arguments sake \(pun intended\) lets say we forgot the order the arguments and we flip the arguments we get an error saying that there was a type mismatch. This is a simple example but say a function takes several arguments that are hard to remember and say some are optional. It's makes it difficult to maintain the order in your head and know if you need certain parameters, this can happen often in practice. Well good old Reason got your back with labelled arguments!
112 |
113 | ```reason
114 | Reason # let getHero sk::sk name::name => {
115 | if (sk) {
116 | let sideKicks = ["robin", "speedy"];
117 | List.find (fun side => name == side) sideKicks;
118 | } else {
119 | let heroes = ["batman", "arrow"];
120 | List.find (fun hero => name == hero) heroes;
121 | }
122 | };
123 | let getHero : sk::bool => name::string => string =
124 |
125 | Reason # getHero name::"batman" sk::false;
126 | - : string = "batman"
127 |
128 | Reason # getHero sk::true name::"robin";
129 | - : string = "robin"
130 | ```
131 |
132 | Above we defined a function called `getHero` that takes 2 labelled arguments, `sk` and `name` . To label an argument you simply pass the label you want the argument to have followed by double colon `::` and then finally the name of the argument you will use in the function. In `getHero` we used the named the label of the argument and the name of the argument the same. Now we can call the arguments in whatever order we want with the label and Reason will know how to apply the parameters and no will no longer throw and error.
133 |
134 | ## Argument Punning
135 |
136 | As we in the Labelled Arguments section the `getHero` function was able to take arguments in any order so long as the label was included when passing in arguments to the function. However when defining functions with labelled arguments there is a neat trick for saving a few keystrokes! In Reason this is called argument punning, you are only able to do this if the label and the name of the argument are the same:
137 |
138 | ```reason
139 | Reason # let getHero sk::sk name::name => {
140 | if (sk) {
141 | let sideKicks = ["robin", "speedy"];
142 | List.find (fun side => name == side) sideKicks;
143 | } else {
144 | let heroes = ["batman", "arrow"];
145 | List.find (fun hero => name == hero) heroes;
146 | }
147 | };
148 | let getHero : sk::bool => name::string => string =
149 |
150 | Reason # getHero name::"batman" sk::false;
151 | - : string = "batman"
152 |
153 | Reason # getHero sk::true name::"robin";
154 | - : string = "robin"
155 | ```
156 |
157 | ## Recursive Functions
158 |
159 | In functional programming languages recursion is important and useful to make code simpler and more concise. Reason is unlike most languages because you have to explicitly tell it that a function is recursive by using the `rec` keyword prior to the definition of the function. The `rec` keyword is the only way a function is able to refer to itself in Reason. If you've ever worked on medium to large codebase it can be difficult to remember which functions are recursive or read code you are not familiar with it may take you a while to realize a function is recursive. In reason you won't have that problem because upon scanning the code you will see the `rec` keyword prior to the function declaration. Lets take a look at recursive function in action:
160 |
161 | ```reason
162 | Reason # let rec sum list =>
163 | switch list {
164 | | [] => 0
165 | | [hd, ...tl] => hd + sum tl
166 | };
167 | let sum : list int => int =
168 |
169 | Reason # sum [1,2,3];
170 | - : int = 6
171 | ```
172 |
173 | The function sum takes a list of type int as an argument, the goal of the function is to iterate through the function and continuously add the values in the list until no items are left traverse. The base case is the first branch in the `switch` that will look at the list passed in and if it is empty it will return 0. The second branch will grab the head of the list in the `hd` variable and then grab the rest of the list in the `tl` variable \(`[hd, ...tl]`\) and then add the `hd` to the recursive `sum` of the `tl` \(`hd + sum tl`\).
174 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/types/readingTypes.md:
--------------------------------------------------------------------------------
1 | # Reading Types
2 |
3 | In the [Core Language section](/core_language.md) of this book, we ran a bunch of code in the REPL. Well, we are going to do it again, but now with an emphasis on the types that are getting spit out. So type fire up your REPL again in your terminal with `npm run top` . You should see this:
4 |
5 | ```reason
6 | ──────────────┬──────────────────────────────────────────────────────────────┬──────────────
7 | │ Welcome to utop version 1.19.2 (using OCaml version 4.02.3)! │
8 | └──────────────────────────────────────────────────────────────┘
9 | Reason: Meta Language Utility
10 | ___ _______ ________ _ __
11 | / _ \/ __/ _ | / __/ __ \/ |/ /
12 | / , _/ _// __ |_\ \/ /_/ / /
13 | /_/|_/___/_/ |_/___/\____/_/|_/
14 |
15 | Execute statements/let bindings. Hit after the semicolon.
16 |
17 | > let myVar = "Hello Reason!";
18 | > let myList: list string = ["first", "second"];
19 |
20 | Type #utop_help for help about using utop.
21 | ```
22 |
23 | ## Primitives and Lists {#primitives-and-lists}
24 |
25 | Let's enter some simple expressions and see what happens:
26 |
27 | ```reason
28 | Reason # "hello";
29 | - : string = "hello"
30 |
31 | Reason # not true;
32 | - : bool = false
33 |
34 | Reason # floor 3.1415;
35 | - : float = 3.
36 | ```
37 |
38 | In these three examples, the REPL tells us what\_type\_of value it along with the resulting value. The value `"hello"` is a `string`. The value `3.` is an `float` . Nothing too crazy here.
39 |
40 | Let's see what happens with lists holding different types of values:
41 |
42 | ```reason
43 | Reason # [ "Alice", "Bob" ];
44 | - : list string = ["Alice", "Bob"]
45 |
46 | Reason # [ 1.0, 8.6, 42.1 ];
47 | - : list float = [1., 8.6, 42.1]
48 |
49 | Reason # [];
50 | - : list 'a = []
51 | ```
52 |
53 | In the first case, we have a `list` filled with `string` values. In the second, the `list` is filled with `float` values. In the third case the list is empty, so we do not actually know what kind of values are in the list. So the type ``list `a`` is saying "I know I have a list, but it could be filled with anything". The lower-case ```a`` is called a_type variable_, meaning that there are no constraints in our program that pin this down to some specific type. In other words, the type can vary based on how it is used.
54 |
55 | ## Functions {#functions}
56 |
57 | Let's see the type of some functions:
58 |
59 | ```reason
60 | Reason # String.length;
61 | - : string => int =
62 | ```
63 |
64 | The function`String.length`has type `string => int`. This means _it must take_ in a `string` argument, and it will definitely return an integer result. So let's try giving it an argument:
65 |
66 | ```reason
67 | Reason # String.length "Supercalifragilisticexpialidocious";
68 | - : int = 34
69 | ```
70 |
71 | The important thing to understand here is how the type of the result `int` is built up from the initial expression. We have a `string => int` function and give it a `string` argument. This results in an `int` .
72 |
73 | What happens when you do not give a `string` though?
74 |
75 | ```reason
76 | Reason # String.length [1,2,3];
77 | Error: This expression has type list 'a
78 | but an expression was expected of type string
79 |
80 | Reason # String.length true;
81 | Error: This expression has type bool but an expression was expected of type
82 | string
83 | ```
84 |
85 | A `string => int` _function must get_ a `string` argument!
86 |
87 | ### Anonymous Functions {#anonymous-functions}
88 |
89 | Reason has a feature called _anonymous functions_. Basically, you can create a function without naming it, like this:
90 |
91 | ```reason
92 | Reason # fun n => n / 2;
93 | - : int => int =
94 | ```
95 |
96 | Defining anonymous functions or lambdas is like defining any function, beginning with the `fun` keyword followed by the list of arguments of the function, and on the right of the arrow, you say what to do with those arguments. In this example, it is saying: I take in some argument I will call `n` and then I am going to divide it by two.
97 |
98 | We can use anonymous functions directly. Here is us using our anonymous function with`128`as the argument:
99 |
100 | ```reason
101 | Reason # (fun n => n / 2)(128);
102 | - : int = 64
103 | ```
104 |
105 | We start with a `int => int` function and give it a `int` argument. The result is another `int` .
106 |
107 | ### Named Functions {#named-functions}
108 |
109 | In the same way that we can name a value, we can name an anonymous function. So rebellious!
110 |
111 | ```reason
112 | Reason # let oneHundredAndTwentyEight = 128.0;
113 | let oneHundredAndTwentyEight : float = 128.
114 |
115 | Reason # let half = fun n => n /. 2.0;
116 | let half : float => float =
117 |
118 | Reason # half oneHundredAndTwentyEight;
119 | - : float = 64.
120 |
121 | Reason # half(oneHundredAndTwentyEight);
122 | - : float = 64.
123 | ```
124 |
125 | In the end, it works just like when nothing was named. You have a `float => float` function, you give it a `float` , and you end up with another `float`. The last two examples are the same, you can choose to optionally include parens on the parameters passed in.
126 |
127 | This is true for all functions, no matter how many arguments they have. So now let's take that a step farther and think about what it means for functions _with multiple arguments_:
128 |
129 | ```reason
130 | Reason # let divide = fun x y => x / y;
131 | let divide : int => int => int =
132 |
133 | Reason # divide 4 2;
134 | - : int = 2
135 | ```
136 |
137 | That seems fine, but why are _there two arrows_ in the type for `divide` ?! To start out, it is fine to think that "all the arguments are separated by arrows, and whatever is last is the result of the function". So `divide` takes two arguments and returns a `int` .
138 |
139 | To really understand why there are two arrows in the type of `divide` , it helps to convert the definition to use anonymous functions.
140 |
141 | ```reason
142 | Reason # let divide = fun x y => x / y;
143 | let divide : int => int => int =
144 |
145 | Reason # let divide = fun x => fun y => x / y;
146 | let divide : int => int => int =
147 | ```
148 |
149 | All of these are totally equivalent. We just moved the arguments over, turning them into anonymous functions one at a time. So when we run an expression like `divide 4 2` we are actually doing a bunch of evaluation steps:
150 |
151 | ```reason
152 | divide 4 2
153 | (divide 4) 2 -- Step 1 - Add the implicit parentheses
154 | ((fun x => (fun y => x / y)) 4) 2 -- Step 2 - Expand `divide`
155 | (fun y => 4 / y) 2 -- Step 3 - Replace x with 3
156 | 4 / 2 -- Step 4 - Replace y with 2
157 | 2 -- Step 5 - Do the math
158 | ```
159 |
160 | After you expand `divide` , you actually provide the arguments one at a time. Replacing `x` and `y` are actually two different steps.
161 |
162 | Let's break that down a bit more to see how the types work. In evaluation step \#3 we saw the following function:
163 |
164 | ```reason
165 | Reason # (fun y => 4 / y);
166 | - : int => int =
167 | ```
168 |
169 | It is a `int => int` function, just like `half` . Now in step \#2 we saw a fancier function:
170 |
171 | ```reason
172 | Reason # (fun x => (fun y => x / y));
173 | - : int => int => int =
174 | ```
175 |
176 | Well, we are starting with `fun x => ...` so we know the type is going to be something like `int => ....` We also know that `(fun y => x / y)` has type `int => int` .
177 |
178 | So if you actually wrote down all the parentheses in the type, it would instead say `int => (int => int)` . You provide arguments one at a time. So when you replace `x` , the result is actually _another function_. The same goes for all functions in Reason.
179 |
180 | Because all functions in Reason work this way, you do not need to give all the arguments at once. It is possible to say things like this:
181 |
182 | ```reason
183 | Reason # divide 128;
184 | - : int => int =
185 | ```
186 |
187 | This is called _partial application_. It lets us use [the`|>`operator](https://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html) to chain functions together in a nice way, and it is why function types have so many arrows!
188 |
189 | ## Type Annotations
190 |
191 | In Reason you are able to use types as much or as little as you want. Types come in handy when trying to figure out input and output of functions, tuples, records, etc. Lets take a look:
192 |
193 | ```reason
194 | let frameworkName : string = "React";
195 |
196 | let manyFrameworks: (string, string, string) = ("React", "Vue", "Angular");
197 |
198 | let stuff = fun (lol: int) => lol;
199 | ```
200 |
201 | ## Type Aliases {#type-annotations}
202 |
203 | So far we have just let Reason figure out the types, but it also lets you write a _type annotation_ on the line above a definition if you want. So when you are writing code, you can say things like this:
204 |
205 | ```reason
206 | type half = int => int;
207 | let half = fun n => n / 2;
208 |
209 | type divide = int => int => int;
210 | let divide = fun x y => x / y;
211 |
212 | type askVegeta = int => string;
213 | let askVegeta = fun powerLevel => {
214 | if (powerLevel >9000) {
215 | "It's over 9000!!!";
216 | } else {
217 | "It is " ^ string_of_int powerLevel ^ ".";
218 | }
219 | };
220 | ```
221 |
222 | People can make mistakes in type annotations, so what happens if they say the wrong thing? Well, the compiler does not make mistakes, so it still figures out the type on its own. It then checks that your annotation matches the real answer. In other words, the compiler will always verify that all the annotations you add are correct.
223 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/coreLanguage/modules.md:
--------------------------------------------------------------------------------
1 | # Modules
2 |
3 | > If you haven't read the [Core Language Overview](/reader/guides/native/anIntroductionToReason/coreLanguage/coreLanguage) please do before diving deeper.
4 |
5 | Modules in Reason give you the ability to wrap up units of code into reusable pieces that you may include in other parts of your codebase. Modules may contain types or values or both. How do modules look?
6 |
7 | ```reason
8 | Reason # module Cool = {
9 | /* cool stuff up in hurr */
10 | };
11 | module Cool : { }
12 | ```
13 |
14 | First things that should catch your eye is that we use `module` keyword instead of the `let` keyword to bind a module to an identifier. Which in this case is `Cool` . Lets populate `Cool` now:
15 |
16 | ```reason
17 | Reason # module Cool = {
18 | type rate = int;
19 | let coolMeter (rating: rate) : string => {
20 | if (rating <= 5) {
21 | "Not Cool";
22 | } else {
23 | "Cool";
24 | }
25 | };
26 | };
27 | module Cool : { type rate = int; let coolMeter : rate => string; }
28 | ```
29 |
30 | As you can see after the `Cool` module definition we are returned the signature of the module. You can access the contents of a module similar to how you access fields on a record. Now we can use the functions and types that `Cool` exposes:
31 |
32 | ```reason
33 | Reason # let tv : Cool.rate = 5;
34 | let tv : int = 5
35 |
36 | Reason # let computer : Cool.rate = 10;
37 | let computer : int = 10
38 |
39 | Reason # Cool.coolMeter tv;
40 | - : string = "Not Cool"
41 |
42 | Reason # Cool.coolMeter computer;
43 | - : string = "Cool"
44 | ```
45 |
46 | #### Rebinding Modules
47 |
48 | When using modules you defined or third party modules in your codebase they may have really long names and it can get really bothersome to constantly type them especially if they are used often. To avoid this you may also bind the module to another identifier:
49 |
50 | ```reason
51 | Reason # module C = Cool;
52 | module C = Cool
53 |
54 | Reason # let tv : C.rate = 5;
55 | let tv : int = 5
56 |
57 | Reason # let computer : C.rate = 10;
58 | let computer : int = 10
59 |
60 | Reason # C.coolMeter tv;
61 | - : string = "Not Cool"
62 |
63 | Reason # C.coolMeter computer;
64 | - : string = "Cool"
65 | ```
66 |
67 | #### Extending Modules
68 |
69 | Modules can be extended with additional functionality by using the `include` keyword. When using the include keyword the module has access to all the modules content:
70 |
71 | ```reason
72 | Reason # module Cool = {
73 | type rate = int;
74 | let coolMeter (rating: rate) : string => {
75 | if (rating <= 5) {
76 | "Not Cool";
77 | } else {
78 | "Cool";
79 | }
80 | };
81 | };
82 | module Cool : { type rate = int; let coolMeter : rate => string; }
83 |
84 | Reason # module SuperDuperCool = {
85 | include Cool;
86 | let superDuperCoolMeter (rating: rate) : string => {
87 | "Super Duper " ^ coolMeter rating;
88 | }
89 | };
90 | module SuperDuperCool :
91 | {
92 | type rate = int;
93 | let coolMeter : rate => string;
94 | let superDuperCoolMeter : rate => string;
95 | }
96 | ```
97 |
98 | `SuperDuperCool` now has all the functionality and content present in `Cool` because we used `include` , but in addition we defined a new function `superDuperCoolMeter` that uses `coolMeter` and super dupefies the result. We can confirm this because `rtop` returns the module signature. Lets take the new Method out for a spin:
99 |
100 | ```reason
101 | Reason # SuperDuperCool.superDuperCoolMeter 9;
102 | - : string = "Super Duper Cool"
103 | ```
104 |
105 | #### Module Signatures
106 |
107 | Similar to many data structures in Reason, modules themselves can be typed. In reason you can type modules by using the `module type` combination. Module typing is referred to as module signature or signatures because signatures describe the structure of values and types that a module contains.
108 |
109 | Lets take a look at a module signature and a module that implements the signature:
110 |
111 | ```reason
112 | Reason # module type CoolStringAndRateInt = {
113 | type rate = int;
114 | let coolMeter: rate => string;
115 | };
116 | module type CoolStringAndRateInt =
117 | { type rate = rating; let coolMeter : rate => string; }
118 |
119 | Reason # module Cool: CoolStringAndRateInt = {
120 | type rate = int;
121 | let coolMeter (rating: rate) : string => {
122 | if (rating <= 5) {
123 | "Not Cool";
124 | } else {
125 | "Cool";
126 | }
127 | };
128 | };
129 | module Cool : CoolStringAndRateInt
130 | ```
131 |
132 | Above we created a `module type` which you can think of as interface or contract that a module must abide by, if it doesn't then the compiler will make sure to let you know and throw a type mismatch.
133 |
134 | In the code above `CoolStringAndRateInt` signature defines a type `int` for the `rate` field. Followed by that, we define a value `coolMeter` . However it may look odd because we don't use `=` when defining it `let coolMeter: rate => string;` This is because we are defining an interface to of a value.
135 |
136 | Finally we revisit the `Cool` module and we set it's signature `module Cool: CoolStringAndRateInt { ... }` . This will enforce the module to abide by the signature, lets take a look:
137 |
138 | ```reason
139 | Reason # module type CoolStringAndRateInt = {
140 | type rate = int;
141 | let coolMeter: rate => string;
142 | };
143 | module type CoolStringAndRateInt =
144 | { type rate = rating; let coolMeter : rate => string; }
145 |
146 | Reason # module Cool: CoolStringAndRateInt = {
147 | let coolMeter (rate: int) : string => {
148 | if (rate <= 5) {
149 | "Not Cool";
150 | } else {
151 | "Cool";
152 | }
153 | };
154 | };
155 | Error: Signature mismatch:
156 | Modules do not match:
157 | { let coolMeter : int => string; }
158 | is not included in
159 | CoolStringAndRateInt
160 | The type `rate' is required but not provided
161 | ```
162 |
163 | If we we're to omit anything specified in the module signature Reason will point it out immediately. This is great from a maintenance and refactoring stand point. Because as soon as the interface of a module changes Reason will tell you about it and help you keep your modules and other code in you codebase that depend on your module stay up to date.
164 |
165 | With that said as long as we satisfy the module signature we get no problems. What if we add more fields or types to a module than what is defined in the signature? 🤔
166 |
167 | ```reason
168 | Reason # module type CoolStringAndRateInt = {
169 | type rate = int;
170 | let coolMeter: rate => string;
171 | };
172 | module type CoolStringAndRateInt =
173 | { type rate = int; let coolMeter : rate => string; }
174 |
175 | Reason # module Cool: CoolStringAndRateInt = {
176 | type rate = int;
177 | let coolMeter (rate: rate) : string => {
178 | if (rate <= 5) {
179 | "Not Cool";
180 | } else {
181 | "Cool";
182 | }
183 | };
184 | let popularityMeter (rate: rate) : string => {
185 | if (rate <= 5) {
186 | "Not Popular";
187 | } else {
188 | "Popular";
189 | }
190 | };
191 | };
192 | module Cool : CoolStringAndRateInt
193 | ```
194 |
195 | Well, if we we're to include additional types or values that we're not defined in the signature they would be hidden. Constraining Modules to a signature might be something you want depending on what you are using it for, it could be useful for hiding implementation details of a module while exposing a public API for the module. Lets take a look and make for certain this is the case:
196 |
197 | ```reason
198 | Reason # module type CoolStringAndRateInt = {
199 | type rate = int;
200 | let coolMeter: rate => string;
201 | };
202 | module type CoolStringAndRateInt =
203 | { type rate = int; let coolMeter : rate => string; }
204 |
205 | Reason # module Cool: CoolStringAndRateInt = {
206 | type rate = int;
207 | let coolMeter (rate: rate) : string => {
208 | if (rate <= 5) {
209 | "Not Cool";
210 | } else {
211 | "Cool";
212 | }
213 | };
214 | let popularityMeter (rate: rate) : string => {
215 | if (rate <= 5) {
216 | "Not Popular";
217 | } else {
218 | "Popular";
219 | }
220 | };
221 | };
222 | module Cool : CoolStringAndRateInt
223 |
224 | Reason # Cool.coolMeter 6;
225 | - : string = "Cool"
226 |
227 | Reason # Cool.popularityMeter 5;
228 | Error: Unbound value Cool.popularityMeter
229 | ```
230 |
231 | As soon as we reach for `popularityMeter` which was not defined in the module signature `CoolStringAndRateInt` Reason lets us know that it's an unbound value, and in effect hiding it from the public API.
232 |
233 | #### Interface Files
234 |
235 | In reason you typically write your code in a `.re` file and this implicitly creates a module that has the capitalized name of the file. However there are also interface reason files with the `.rei` extension, that will create a module signature for the corresponding `.re` file.
236 |
237 | So lets say we define a `Cool.re` file with the following contents:
238 |
239 | ```reason
240 | type rate = int;
241 | let coolMeter (rate: rate) : string => {
242 | if (rate <= 5) {
243 | "Not Cool";
244 | } else {
245 | "Cool";
246 | }
247 | };
248 | ```
249 |
250 | With a corresponding `Cool.rei` file :
251 |
252 | ```reason
253 | type rate = int;
254 | let coolMeter: rate => string;
255 | ```
256 |
257 | In this case the `Cool.rei` file will constrain the `Cool.re` file because it will contain the module signature of `Cool.re` . Aside from this `.rei` files can be useful to developers because you can quickly scan over the public API of the corresponding `.re` file.
258 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/coreLanguage/coreLanguage.md:
--------------------------------------------------------------------------------
1 | # Core Language
2 |
3 | This is quick overview of the Reason Language.
4 |
5 | Follow along by running the Reason REPL and typing the commands into the repl
6 |
7 | ```bash
8 | npm run top
9 | ```
10 |
11 | After running the previous command you should see the following:
12 |
13 | ```reason
14 | ──────────────┬──────────────────────────────────────────────────────────────┬──────────────
15 | │ Welcome to utop version 1.19.2 (using OCaml version 4.02.3)! │
16 | └──────────────────────────────────────────────────────────────┘
17 | Reason: Meta Language Utility
18 | ___ _______ ________ _ __
19 | / _ \/ __/ _ | / __/ __ \/ |/ /
20 | / , _/ _// __ |_\ \/ /_/ / /
21 | /_/|_/___/_/ |_/___/\____/_/|_/
22 |
23 | Execute statements/let bindings. Hit after the semicolon.
24 |
25 | > let myVar = "Hello Reason!";
26 | > let myList: list string = ["first", "second"];
27 |
28 | Type #utop_help for help about using utop.
29 | ```
30 |
31 | If you see this everything is working great! If not please consult [Get Up & Running.](/get_up_and_running.md)
32 |
33 | To exit the REPL, type `ctrl + d`
34 |
35 | # Values
36 |
37 | ## Strings
38 |
39 | ```reason
40 | Reason # "hello";
41 | - : string = "hello"
42 |
43 | Reason # "Hello, " ^ "from Reason";
44 | - : string = "Hello, from Reason"
45 | ```
46 |
47 | Reason uses the `^` operator to put strings together.
48 |
49 | ## Numbers
50 |
51 | ```reason
52 | Reason # 2 + 3 * 4;
53 | - : int = 14
54 |
55 | Reason # (2 + 3) * 4;
56 | - : int = 20
57 | ```
58 |
59 | Reason makes a distinction between integers and floating point numbers. Unlike some other languages, Reason won't automatically convert integer literals to floats, you must explicitly write them with a decimal point as seen below. There is both floating point division `/.` and integer division `/` . The same convention goes for the other arithmetic operators.
60 |
61 | ```reason
62 | Reason # 9.0 /. 2.0;
63 | - : float = 4.5
64 |
65 | Reason # 9/2;
66 | - : int = 4
67 | ```
68 |
69 | ## Functions
70 |
71 | ```reason
72 | Reason # let isNegative n => n < 0;
73 | let isNegative : int => bool =
74 |
75 | Reason # isNegative 4;
76 | - : bool = false
77 |
78 | Reason # isNegative (-7);
79 | - : bool = true
80 |
81 | Reason # isNegative (-3 * -4);
82 | - : bool = false
83 | ```
84 |
85 | In reason to invoke/call a function you can simply choose to use parenthesis or omit/ignore them. Whichever one you prefer to use. The first piece of code we entered to define isNegative returns the type definition of the function. We will get into type definitions later in this guide.
86 |
87 | ```reason
88 | Reason # let sum2 a b => a + b;
89 | let sum2 : int => int => int =
90 |
91 | Reason # sum2 1 2;
92 | - : int = 3
93 |
94 | Reason # sum2 1 (sum2 2 3);
95 | - : int = 6
96 | ```
97 |
98 | Function calling in Reason looks different than it does in languages like Javascript, Java or C. The arguments are passed in plainly one at a time without being comma-separated. As you can see in the above example, parentheses are used differently as well. They can be omitted when the argument is simple, such as in the second example, but in the third example, the second argument to sum2 is more complex, so we wrap it in parentheses. You can read more about this in the [Functions](https://kennetpostigo.gitbooks.io/an-introduction-to-reason/content/Core%20Language/Functions.html) section under "Multiargument Functions & Gotchas".
99 |
100 | ## If Expressions
101 |
102 | ```reason
103 | Reason # if (true) {
104 | "Hello";
105 | } else {
106 | "World";
107 | };
108 | - : string = "Hello"
109 |
110 | Reason # if (false) {
111 | "Hello";
112 | } else {
113 | "World";
114 | };
115 | - : string = "World"
116 | ```
117 |
118 | Reason `if/else` expressions should look familiar to you if you've ever dabbled in C, C++, and Javascript. One major difference is that they are expressions in Reason, meaning they always return a value.
119 |
120 | Reason does not have a notion of “truthiness” so numbers and strings and lists cannot be used as boolean values. If we try it out, Reason will tell us that we need to work with a real boolean value.
121 |
122 | Now let's make a function that tells us if a number is over 9000.
123 |
124 | ```reason
125 | Reason # let over9000 powerLevel => {
126 | if (powerLevel > 9000) {
127 | "It's Greater Than 9000";
128 | } else {
129 | "meh";
130 | }
131 | };
132 | let over9000 : int => string =
133 |
134 | Reason # over9000 42;
135 | - : string = "meh"
136 |
137 | Reason # over9000 100000;
138 | - : string = "It's Greater Than 9000"
139 | ```
140 |
141 | Here you can notice that we add `{ ... }` to define multi-line functions. `over9000` combines the usage of `functions` and `if/else` control flow.
142 |
143 | ## Lists
144 |
145 | Lists are one of the most common data structures in Reason. They hold a sequence of related things, similar to arrays in C++, Javascript, and Java. You can think of them as a singly-linked list.
146 |
147 | Lists can hold many values. Those values must all have the same type. Here are a few examples that use functions from
148 |
149 | [the`List`library](https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html):
150 |
151 | ```reason
152 | Reason # let names = [ "Alice", "Bob", "Chuck" ];
153 | let names : list string = ["Alice", "Bob", "Chuck"]
154 |
155 | Reason # List.length(names) > 0;
156 | - : bool = true
157 |
158 | Reason # List.length names;
159 | - : int = 3
160 |
161 | Reason # List.rev names;
162 | - : list string = ["Chuck", "Bob", "Alice"]
163 |
164 | Reason # let numbers = [1,4,3,2];
165 | let numbers : list int = [1, 4, 3, 2]
166 |
167 | Reason # List.sort compare numbers;
168 | - : list int = [1, 2, 3, 4]
169 |
170 | Reason # let double = fun n => n * 2;
171 | let double : int => int =
172 |
173 | Reason # List.map double numbers;
174 | - : list int = [2, 8, 6, 4]
175 | ```
176 |
177 | ## Tuples
178 |
179 | Tuples are another useful data structure. A tuple can hold a fixed number of values, and each value can have any type. A common use is if you need to return more than one value from a function. The following function gets a name and gives a message for the user:
180 |
181 | ```reason
182 | Reason # let goodName name => {
183 | if ((String.length name) <= 20) {
184 | (true, "name accepted!");
185 | } else {
186 | (false, "name was too long; please limit it to 20 characters");
187 | }
188 | };
189 | let goodName : string => (bool, string) =
190 |
191 | Reason # goodName("Tom");
192 | - : (bool, string) = (true, "name accepted!")
193 | ```
194 |
195 | This can be quite handy, but when things start becoming more complicated, it is often best to use records instead of tuples.
196 |
197 | ## Records
198 |
199 | A record is a set of key-value pairs, similar to objects in JavaScript or Python. You will find that they are extremely common and useful in Reason! Let's see some basic examples.
200 |
201 | ```reason
202 | Reason # type point = { x: int, y: int };
203 | type point = { x : int, y : int, }
204 |
205 | Reason # let cursor = { x: 3, y: 4 };
206 | let cursor : point = {x : 3, y : 4}
207 |
208 | Reason # cursor.x;
209 | - : int = 3
210 |
211 | Reason # type person = { name: string, age: int };
212 | type person = { name : string, age : int, }
213 |
214 | Reason # let bill = { name: "Gates", age: 57 };
215 | let bill : person = {name : "Gates", age : 57}
216 |
217 | Reason # bill.name;
218 | - : string = "Gates"
219 | ```
220 |
221 | To create a record you must first define a `type definition` with the shape that the record will abide by. Type definitions are distinguishable with the fact that they start with the keyword `type` instead of `let` and instead of assigning values for the fields on you assign types, ie: `x: int` . Once the type is defined you can create a record that has the same shape as the type.
222 |
223 | If you want to access the values on a record simply use `someRecord.field` .
224 |
225 | It is often useful to update the values in a record. You can do this on fields you mark fields on the type definition with mutable:
226 |
227 | ```reason
228 | Reason # type point = { mutable x: int, y: int };
229 | type point = { mutable x : int, y : int, }
230 |
231 | Reason # let cursor = { x: 2, y: 5 };
232 | let cursor : point = {x : 2, y : 5}
233 |
234 | Reason # cursor.x = 12;
235 | - : unit = ()
236 |
237 | Reason # cursor.x;
238 | - : int = 12
239 |
240 | Reason # cursor.y = 5;
241 | Error: The record field y is not mutable
242 | ```
243 |
244 | Only fields marked with mutable can be changed, if you attempt to update a non mutable field you will receive an error from Reason telling you exactly this.
245 |
246 | ## Comparing Records and Javascript Objects
247 |
248 | Records in Reason are _similar_ to objects in Javascript, but there are some crucial differences. The major differences are that with records:
249 |
250 | * You cannot ask for a field that does not exist.
251 | * No field will ever be undefined or null.
252 | * Records are Immutable
253 |
254 | ## Diving Deeper
255 |
256 | If you want to learn about each of the core language sections deeper:
257 | * [Functions](/reader/guides/native/anIntroductionToReason/coreLanguage/functions)
258 | * [Records](/reader/guides/native/anIntroductionToReason/coreLanguage/records)
259 | * [Objects](/reader/guides/native/anIntroductionToReason/coreLanguage/objects)
260 | * [Lists](/reader/guides/native/anIntroductionToReason/coreLanguage/lists)
261 | * [Tuples](/reader/guides/native/anIntroductionToReason/coreLanguage/tuples)
262 | * [Modules](/reader/guides/native/anIntroductionToReason/coreLanguage/modules)
263 | * [Functors](/reader/guides/native/anIntroductionToReason/coreLanguage/functors)
264 |
265 |
--------------------------------------------------------------------------------
/guides/native/anIntroductionToReason/types/variants.md:
--------------------------------------------------------------------------------
1 | # Variants
2 |
3 | Many languages have trouble expressing data with weird shapes. They give you a small set of built-in types, and you have to represent everything with them. So you often find yourself using `null` or booleans or strings to encode details in a way that is quite error prone.
4 |
5 | _Reasons_ _variants_ let you represent complex data much more naturally. We will go through a couple concrete examples to build some intuition about how and when to user variants.
6 |
7 | > **Note: **Variants are sometimes called Union types or [tagged unions](https://en.wikipedia.org/wiki/Tagged_union). Some communities call them [ADTs](https://en.wikipedia.org/wiki/Algebraic_data_type).
8 |
9 | ## Filtering a Todo List
10 |
11 | > **Problem:** We are creating a todo list full of tasks. We want to have three views: show all tasks, show only active tasks, and show only completed tasks. How do we represent which of these three states we are in?
12 |
13 | ```reason
14 | Reason # type Visibility =
15 | | All
16 | | Active
17 | | Completed;
18 |
19 | Reason # All;
20 | - : Visibility = All
21 |
22 | Reason # Active;
23 | - : Visibility = Active
24 |
25 | Reason # Completed;
26 | - : Visibility = Completed
27 | ```
28 |
29 | Now that we have these three cases defined, we want to create a function keep that will properly filter our tasks. It should work like this:
30 |
31 | ```reason
32 | type task = {
33 | task: string,
34 | complete: bool
35 | };
36 |
37 | type buy = task;
38 | let buy = {
39 | task: "Buy milk",
40 | complete: true
41 | };
42 |
43 | type drink = task;
44 | let drink = {
45 | task: "Drink milk",
46 | complete: false
47 | };
48 |
49 | type tasks = list task;
50 | let tasks = [buy, drink];
51 |
52 | # type keep = Visibility => List Task => List Task;
53 | # keep All tasks == [buy, drink];
54 | # keep Active tasks == [drink];
55 | # keep Complete tasks == [buy];
56 | ```
57 |
58 | So they `keep` function needs to look at its first argument, and depending on what it is, filter the list in various ways. We use a `switch` expression to do this. It is like an `if` on steroids:
59 |
60 | ```reason
61 | type keep = visibility => list task => list tasks;
62 | let keep = fun visibility tasks => {
63 | switch visibility {
64 | | All => tasks;
65 | | Active => List.filter (fun task => not task.complete) tasks;
66 | | Completed => List.filter (fun task => task.complete) tasks;
67 | };
68 | };
69 | ```
70 |
71 | The `switch` is saying, look at the structure of visibility. If it is `All` , just give back all the tasks. If it is `Active` , keep only the tasks that are not complete. If it is `Complete` , keep only the tasks that are complete.
72 |
73 | The cool thing about switch expression is that all the branches are checked by the compiler. This has some nice benefits:
74 |
75 | 1. If you mistype `Compleet` by accident, you get a hint about the typo.
76 | 2. If you forget to handle a case, the compiler will figure it out and tell you.
77 |
78 | So say you want to add `Recent` as a fourth possible `Visibility` value. The compiler will find all the `switch` expressions in your code that work with `Visibility` values and remind you to handle the new possibility! This means you can change and extend `Visibility` without the risk of silently creating bugs in existing code.
79 |
80 | ## Anonymous Users
81 |
82 | > **Problem:** We have a chat room where people can post whatever they want. Some users are logged in and some are anonymous. How should we represent a user?
83 |
84 | Again, whenever there is weird shaped data, you want to reach for a variant. For this case we want one where users are either anonymous or named:
85 |
86 | ```reason
87 | Reason # type user =
88 | | Anonymous
89 | | Named string;
90 |
91 | Reason # Anonymous;
92 | - : user = Anonymous
93 |
94 | Reason # Named "AzureDiamond";
95 | - : user = Named "AzureDiamond"
96 |
97 | Reason # Named "abraham-lincoln";
98 | - : user = Named "abraham-lincoln"
99 | ```
100 |
101 | So creating the type `user` also created constructors named `Anonymous` and `Named`. If you want to create a `user` you _must_ use one of these two constructors. This guarantees that all the possible `user` values are things like:
102 |
103 | ```reason
104 | Anonymous
105 | Named "AzureDiamond"
106 | Named "abraham-lincoln"
107 | Named "catface420"
108 | Named "Tom"
109 | ...
110 | ```
111 |
112 | Now that we have a representation of a `user`, lets say we want to get a photo of the to show next to their posts. Again, we need to use a `case` expression to work with out `user` type:
113 |
114 | ```reason
115 | type userPhoto = user -> string;
116 | let userPhoto = switch user {
117 | | Anonymous => "anon.png";
118 | | Named name => "users/" ^ name ^ ".png";
119 | };
120 | ```
121 |
122 | There are two possible cases when we have a `user`. If they are `Anonymous` we show a dummy picture. If they are `Named` we construct the URL of their photo. This `switch` is slightly fancier than the one we saw before. Notice that the second branch has a lower case variable name. This means that when we see a value like Named `"AzureDiamond"` , the `name` variable will be bound to `"AzureDiamond"` so we can do other things with it. This is called _pattern matching_.
123 |
124 | Now imagine we have a bunch of users in a chat room and we want to show their pictures.
125 |
126 | ```reason
127 | type activeUsers = list user;
128 | let activeUsers = [Anonymous, Named "catface420", Named "AzureDiamond", Anonymous];
129 |
130 | type photos = list string;
131 | let photos = list.map userPhoto activeUsers;
132 |
133 | # [ "anon.png", "users/catface420.png", "users/AzureDiamond.png", "anon.png" ];
134 | ```
135 |
136 | The nice thing about creating a type like `user` is that no one in your whole codebase can ever "forget" that some users may be anonymous. Anyone who can get a hold of a `user` needs to use a `switch` to get any information out of it, and the compiler guarantees every `case` and handles all possible scenarios!
137 |
138 | ## Widget Dashboard
139 |
140 | > **Problem: **You are creating a dashboard with three different kinds of widgets. One shows a recent log data, one shows time plots, and one shows scatter plots. How do you represent a widget?
141 |
142 | Alright, we are getting a bit fancier now. In Reason, you want to start by solving each case individually. \(As you get more experience, you will see that Reason _wants_ you to build programs out of small, reusable parts. It is weird.\) So I would create representations for each of our three scenarios, along with view functions to actually turn them into HTML or SVG or whatever:
143 |
144 | ```reason
145 | type logsInfo = {
146 | logs: list string
147 | };
148 |
149 | type timeInfo = {
150 | events: list (string, float),
151 | yAxis: string
152 | };
153 |
154 | type scatterInfo = {
155 | points: list (float, float),
156 | xAxis: string,
157 | yAxis: string
158 | };
159 | ```
160 |
161 | At this point you have created all the helper functions needed to work with these three cases totally independent from each other. Someone can come along later and say, "I need a nice way to show scatter plots" and use just that part of code.
162 |
163 | So the question is really: how do I put these three standalone things together in my particular scenario?
164 |
165 | Again, variants are there to put a bunch of different types!
166 |
167 | ```reason
168 | Reason # type widget =
169 | | Logs logsInfo
170 | | TimePlot timeInfo
171 | | ScatterPlot scatterInfo;
172 | ```
173 |
174 | So we created a widget type that can only be created with these constructor functions. You can think of these constructors as tagging the data so we can tell it apart at runtime
175 |
176 | ```reason
177 | type view = widget;
178 |
179 | let view = switch widget {
180 | | Logs logsInfo => logsInfo;
181 | | TimePlot timeInfo => timeInfo;
182 | | ScatterPlot scatterInfo => scatterInfo;
183 | };
184 | ```
185 |
186 | One nice thing about this approach is that there is no mystery about what kind of widgets are supported. There are exactly three. If someone wants to add a fourth, they modify the `widget` type. This means you can never be surprised by the data you get, even if someone on a different team is messing with your code.
187 |
188 | > **Takeaways:**
189 | >
190 | > * Solve each subproblem first.
191 | > * Use variants to put together all the solutions.
192 | > * Creating a variant type generates a bunch of _constructors_.
193 | > * These constructors _tag_ data so that we can differentiate it at runtime.
194 | > * A `switch` expression lets us tear data apart based on these tags.
195 | >
196 | > The same strategies can be used if you are making a game and have a bunch of different bad guys. Goombas should update one way, but Koopa Troopas do something totally different. Solve each problem independently, and then use a union type to put them all together.
197 |
198 | ## Linked Lists
199 |
200 | > **Problem:** You are stuck on a bus speeding down the highway. If the bus slows down, it will blow up. The only way to save yourself and everyone on the bus is to reimplement linked lists in Reason. HURRY, WE ARE RUNNING OUT OF GAS!
201 |
202 | Yeah, yeah, the problem is contrived this time, but it is important to see some of the more advanced things you can do with variants!
203 |
204 | A [linked list](https://en.wikipedia.org/wiki/Linked_list) is a sequence of values. If you are looking at a linked list, it is either empty or it is a value and more more list. That list is either empty or is a value and more list. etc. This intuitive definition works pretty directly in Reason Let's see it for lists of integers:
205 |
206 | ```reason
207 | Reason # type intList = Empty | Node int intList;
208 |
209 | Reason # Empty;
210 | - : intList = Empty
211 |
212 | Reason # Node 42 None;
213 | - : intList = Node 42 Empty
214 |
215 | Reason # Node 64 (Node 128 Empty);
216 | - : intList = Node 64 (Node 128 Empty)
217 | ```
218 |
219 | Now we did two new things here:
220 |
221 | 1. The `Node` constructor takes two arguments instead of one. This is fine. In fact, you can have them take as many arguments as you want.
222 | 2. Our variant type is _recursive_. An `intList` may hold another `intList`. Again, this is fine if you are using variant types.
223 |
224 | The nice thing about our intList type is that now we can only build valid linked lists. Every linked list needs to start with `Empty` and the only way to add a new value is with `Node`.
225 |
226 | It is equally nice to work with. Let's say we want to compute the sum of all of the numbers in a list. Just like with any other union type, we need to use a switch and handle all possible scenarios:
227 |
228 | ```reason
229 | type sum = intList => int;
230 | let rec sum = fun numbers =>
231 | switch numbers {
232 | | Empty => 0;
233 | | Node n remainingNumbers => n + sum remainingNumbers;
234 | };
235 | ```
236 |
237 | If we get an `Empty` value, then the sum is 0. If we have a `Node` we add the first element to the sum of all the remaining ones. So an expression like `(sum (Node 1 (Node 2 (Node 3 Empty))))` is evaluated like this:
238 |
239 | ```reason
240 | sum (Node 1 (Node 2 (Node 3 Empty)))
241 | 1 + sum (Node 2 (Node 3 Empty))
242 | 1 + (2 + sum (Node 3 Empty))
243 | 1 + (2 + (3 + sum Empty))
244 | 1 + (2 + (3 + 0))
245 | 1 + (2 + 3)
246 | 1 + 5
247 | 6
248 | ```
249 |
250 | On each line, we see one evaluation step. When we call `sum` it transforms the list based on whether it is looking at a `Node` or and `Empty` value.
251 |
252 | > **Note: **This is the first recursive function we have written together! Notice that the assignment of has the keyword `rec` to explicitly let you know that the `sum` is recursive, and `sum` calls itself to get the sum. It can be tricky to get into the mindset of writing recursive functions, so I wanted to share one weird trick. **Pretend you are already done.**
253 | >
254 | > I always start with a `switch` and all of the branches listed but not filled in. From there, I solve each branch one at a time, pretending that nothing else exists. So with `sum` I'd look at `Empty =>` and say, and empty list has to sum to zero. Then I'd look at the `Node n remainingNumbers =>` branch and think, well, I know I have a number, a list, and a sum function that definitely already exists and totally works. I can just use that and add a number to it!
255 |
256 | ## Generic Data Structures
257 |
258 | > **Problem:** The last section showed lined lists that only worked for integers. That is pretty lame. How can we make linked lists that hold any kind of value?
259 |
260 | Everything is going to be pretty much the same, except we are going to introduce a type variable in our definition of lists:
261 |
262 | ```reason
263 | Reason # type linkList 'a = Empty | Node 'a (linkList 'a);
264 | type linkList 'a = Empty | Node of 'a linkList 'a
265 |
266 | Reason # Empty;
267 | - : linkList 'a = Empty
268 |
269 | Reason # Node "hi" Empty;
270 | - : linkList string = Node "hi" Empty
271 |
272 | Reason # Node 1.618 (Node 6.283 Empty);
273 | - : linkList float = Node 1.618 (Node 6.283 Empty)
274 | ```
275 |
276 | The fancy part comes in the `Node` constructor. Instead of pinning the data to `int` and `intList` , we say that it can hold ```a`` and ``linkList `a`` . Basically, you can add a value as long as it is the same type of value as everything else in the list.
277 |
278 | Everything else is the same. You pattern match on lists with switch and you write recursive functions. The only difference is that our lists ca hold anything now!
279 |
280 | ## Languages
281 |
282 | We can even model a programming language as data if we want to go really crazy! In this case it is one that only deals with [Boolean algebra](https://en.wikipedia.org/wiki/Boolean_algebra#Operations):
283 |
284 | ```reason
285 | type boolean =
286 | | T
287 | | F
288 | | Not boolean
289 | | And boolean boolean
290 | | Or boolean boolean;
291 |
292 | let customOr = Or T F;
293 |
294 | let customAnd = And T T
295 |
296 | let customBoolAlgebra = And T (Not T);
297 | ```
298 |
299 |
300 |
--------------------------------------------------------------------------------
/src/components/Standalone/Logo.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | function Logo(props) {
4 | return (
5 |
96 | );
97 | }
98 |
99 | export default Logo;
100 |
--------------------------------------------------------------------------------