├── documentation └── native │ └── reason │ ├── string │ ├── equal.md │ ├── compare.md │ ├── lowercase_ascii.md │ ├── split_on_char.md │ ├── uppercase_ascii.md │ ├── capitalize_ascii.md │ ├── uncapitalize_ascii.md │ ├── length.md │ ├── iter.md │ ├── capitalize.md │ ├── escaped.md │ ├── uppercase.md │ ├── iteri.md │ ├── lowercase.md │ ├── make.md │ ├── uncapitalize.md │ ├── string.md │ ├── init.md │ ├── contains.md │ ├── rindex.md │ ├── index.md │ ├── concat.md │ ├── trim.md │ ├── map.md │ ├── sub.md │ ├── get.md │ ├── contains_from.md │ ├── index_from.md │ ├── rindex_from.md │ ├── rcontains_from.md │ └── mapi.md │ ├── meta.md │ ├── tableOfContents.md │ ├── list │ ├── flatten.md │ ├── rev.md │ ├── hd.md │ ├── length.md │ ├── concat.md │ ├── tl.md │ ├── append.md │ ├── rev_append.md │ ├── nth.md │ ├── list.md │ └── cons.md │ ├── array │ ├── of_list.md │ ├── to_list.md │ ├── length.md │ ├── copy.md │ ├── concat.md │ ├── create_float.md │ ├── make.md │ ├── append.md │ ├── init.md │ ├── array.md │ ├── sub.md │ ├── make_matrix.md │ ├── fill.md │ ├── get.md │ ├── set.md │ └── blit.md │ └── introduction.md ├── src ├── styles │ ├── index.js │ └── rdn.css ├── assets │ ├── Grid.png │ ├── Logo.png │ ├── banner.png │ └── app-icon-192.png ├── components │ ├── Resources │ │ ├── styles │ │ │ ├── Listing.css │ │ │ ├── Resources.css │ │ │ ├── Selection.css │ │ │ └── Dropdown.css │ │ ├── Listing.js │ │ ├── index.js │ │ ├── Selection.js │ │ └── Dropdown.js │ ├── Standalone │ │ ├── styles │ │ │ ├── Edit.css │ │ │ ├── Languages.css │ │ │ ├── Card.css │ │ │ ├── Navbar.css │ │ │ └── CodeBlock.css │ │ ├── Link.js │ │ ├── Languages.js │ │ ├── Card.js │ │ ├── Markdown.js │ │ ├── Edit.js │ │ ├── AsyncMarkdown.js │ │ ├── AsyncComponent.js │ │ ├── Navbar.js │ │ ├── CodeBlock.js │ │ └── Logo.js │ ├── Community │ │ ├── styles │ │ │ └── Community.css │ │ ├── Community.md │ │ └── index.js │ ├── ToolChain │ │ ├── styles │ │ │ └── Toolchain.css │ │ ├── index.js │ │ └── Tooling.md │ ├── Home │ │ ├── styles │ │ │ └── Home.css │ │ └── index.js │ ├── Reader │ │ ├── ReaderMenu.js │ │ ├── index.js │ │ └── styles │ │ │ ├── Reader.css │ │ │ └── ReaderMenu.css │ └── index.js ├── manifest.json ├── index.js ├── index.html ├── swm.js └── markdown.js ├── guides └── native │ └── anIntroductionToReason │ ├── meta.md │ ├── coreLanguage │ ├── objects.md │ ├── tuples.md │ ├── functors.md │ ├── lists.md │ ├── records.md │ ├── functions.md │ ├── modules.md │ └── coreLanguage.md │ ├── tableOfContents.md │ ├── types │ ├── types.md │ ├── typeAliases.md │ ├── readingTypes.md │ └── variants.md │ ├── introduction.md │ └── getUpNRunning.md ├── .gitignore ├── .babelrc ├── server.js ├── package.json ├── README.md └── webpack.config.js /documentation/native/reason/string/equal.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation/native/reason/string/compare.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation/native/reason/string/lowercase_ascii.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation/native/reason/string/split_on_char.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation/native/reason/string/uppercase_ascii.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation/native/reason/string/capitalize_ascii.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation/native/reason/string/uncapitalize_ascii.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/styles/index.js: -------------------------------------------------------------------------------- 1 | import 'typeface-montserrat'; 2 | import './rdn.css' -------------------------------------------------------------------------------- /documentation/native/reason/meta.md: -------------------------------------------------------------------------------- 1 | The reason toolchain reference documentation. -------------------------------------------------------------------------------- /src/assets/Grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennetpostigo/rdn/HEAD/src/assets/Grid.png -------------------------------------------------------------------------------- /src/assets/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennetpostigo/rdn/HEAD/src/assets/Logo.png -------------------------------------------------------------------------------- /guides/native/anIntroductionToReason/meta.md: -------------------------------------------------------------------------------- 1 | A beginners guide to Reason, its toolchain, and more! -------------------------------------------------------------------------------- /src/assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennetpostigo/rdn/HEAD/src/assets/banner.png -------------------------------------------------------------------------------- /src/assets/app-icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennetpostigo/rdn/HEAD/src/assets/app-icon-192.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | flow-typed 3 | .DS_Store 4 | .nyc_output 5 | coverage 6 | .git 7 | sample 8 | .vscode 9 | dist -------------------------------------------------------------------------------- /src/components/Resources/styles/Listing.css: -------------------------------------------------------------------------------- 1 | .listing{ 2 | display: flex; 3 | flex-direction: row; 4 | flex-wrap: wrap; 5 | justify-content: space-around; 6 | width: 100%; 7 | } -------------------------------------------------------------------------------- /src/components/Standalone/styles/Edit.css: -------------------------------------------------------------------------------- 1 | .edit { 2 | display: flex; 3 | background: #FD7E6A; 4 | color: #fff; 5 | border: none; 6 | padding: 5px; 7 | border-radius: 3px; 8 | margin: 5px; 9 | } -------------------------------------------------------------------------------- /src/components/Standalone/styles/Languages.css: -------------------------------------------------------------------------------- 1 | .languages { 2 | display: flex; 3 | background: #F2F2F2; 4 | color: #000; 5 | border: none; 6 | padding: 5px; 7 | border-radius: 3px; 8 | margin: 5px; 9 | } -------------------------------------------------------------------------------- /src/components/Community/styles/Community.css: -------------------------------------------------------------------------------- 1 | .community-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 | } -------------------------------------------------------------------------------- /src/components/Resources/styles/Resources.css: -------------------------------------------------------------------------------- 1 | .resources-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 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "es2015", 5 | { 6 | "modules": false 7 | } 8 | ], 9 | "stage-2", 10 | "react" 11 | ], 12 | "plugins": [ 13 | "syntax-dynamic-import" 14 | ] 15 | } -------------------------------------------------------------------------------- /src/components/Standalone/Link.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link as RLink } from 'react-router-dom'; 3 | 4 | function Link(props) { 5 | return ( 6 | {props.children} 7 | ); 8 | } 9 | 10 | export default Link; 11 | -------------------------------------------------------------------------------- /src/components/Standalone/Languages.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './styles/Languages.css'; 3 | 4 | // When click should show a dropdown of the languages available 5 | function Languages(props) { 6 | return ; 7 | } 8 | 9 | export default Languages; 10 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Reason Developer Network", 3 | "short_name": "RDN", 4 | "theme_color": "#CE5643", 5 | "background_color": "#fff", 6 | "display": "standalone", 7 | "start_url": "/", 8 | "icons": [ 9 | { 10 | "src": "/assets/Logo.png", 11 | "sizes": "192x192" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import App from './components'; 4 | import runtime from 'offline-plugin/runtime'; 5 | 6 | runtime.install({ 7 | onUpdateReady: () => runtime.applyUpdate(), 8 | onUpdated: () => location.reload() 9 | }); 10 | 11 | render(, document.getElementById('root')); 12 | -------------------------------------------------------------------------------- /documentation/native/reason/tableOfContents.md: -------------------------------------------------------------------------------- 1 | #### Reason 2 | 3 | 4 | + [Introduction](/reader/documentation/native/reason/introduction) 5 | + [List]() 6 | + [Array]() 7 | + [Queue]() 8 | + [Sets]() 9 | + [Map]() 10 | + [Hashtbl]() 11 | + [String]() 12 | + [Data Types]() 13 | + [Functions]() 14 | + [Object]() 15 | + [Unix]() 16 | + [Module]() 17 | + [Functor]() -------------------------------------------------------------------------------- /src/components/Standalone/Card.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import './styles/Card.css'; 4 | 5 | function Card(props) { 6 | return ( 7 |
8 |

{props.title}

9 | {props.children} 10 |

Read More

11 |
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 |
17 | {listing.map((key, i) => ( 18 | 25 | {test(category, technology, key)} 26 | 27 | ))} 28 |
29 | ); 30 | } 31 | 32 | export default Listing; 33 | -------------------------------------------------------------------------------- /src/components/Resources/styles/Dropdown.css: -------------------------------------------------------------------------------- 1 | .dropdown-closed{ 2 | display: flex; 3 | color: #fff; 4 | font-weight: 400; 5 | } 6 | 7 | .dropdown-closed h1{ 8 | margin: 0 5px; 9 | color: #fff; 10 | font-weight: 400; 11 | } 12 | 13 | .dropdown-open-initial h1{ 14 | margin: 0 5px; 15 | color: #fff; 16 | font-weight: 400; 17 | } 18 | 19 | .dropdown-open { 20 | display: flex; 21 | flex-direction: column; 22 | font-weight: 400; 23 | } 24 | .dropdown-open-initial{ 25 | display: flex; 26 | color: #fff; 27 | font-weight: 400; 28 | } 29 | .dropdown-open ul{ 30 | background: #fff; 31 | box-shadow: 0 1px 3px rgba(202,202,202,0.12), 0 1px 2px rgba(115,115,115,0.24); 32 | padding: 10px; 33 | position: absolute; 34 | font-weight: 400; 35 | } 36 | .dropdown-open ul li h2{ 37 | color: #000; 38 | list-style: none; 39 | font-weight: 400; 40 | margin: 2px auto; 41 | } 42 | 43 | .dropdown-open ul li { 44 | color: #000; 45 | list-style: none; 46 | font-weight: 400; 47 | margin: 0; 48 | } 49 | 50 | .dropdown a { 51 | margin: 0; 52 | } -------------------------------------------------------------------------------- /src/styles/rdn.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: 'Montserrat'; 3 | font-weight: 300; 4 | } 5 | body{ 6 | margin: 0; 7 | padding: 0; 8 | } 9 | a { 10 | color: #dd4b39; 11 | text-decoration: none; 12 | } 13 | a:hover { 14 | color: #b13c2e; 15 | } 16 | .container { 17 | display: flex; 18 | justify-content: center; 19 | width: 100%; 20 | } 21 | .child-container { 22 | display: flex; 23 | flex-direction: column; 24 | align-items: center; 25 | margin-top: 80px; 26 | width: 100%; 27 | } 28 | .content-container { 29 | display: flex; 30 | flex-direction: column; 31 | width: 100%; 32 | max-width: 800px; 33 | padding: 30px 0px; 34 | } 35 | .markdown-container { 36 | display: flex; 37 | flex-direction: column; 38 | justify-content: space-around; 39 | width: 100%; 40 | max-width: 750px; 41 | padding: 30px 0px; 42 | margin-bottom: 50px; 43 | } 44 | .content-container-spacer { 45 | display: flex; 46 | max-width: 700px; 47 | padding: 30px 0px; 48 | margin-top: 80px; 49 | } 50 | .rdn-options { 51 | display: flex; 52 | align-self: flex-end; 53 | } 54 | -------------------------------------------------------------------------------- /src/components/Resources/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Edit from './../Standalone/Edit.js'; 3 | import Languages from './../Standalone/Languages.js'; 4 | import Dropdown from './Dropdown.js'; 5 | import Selection from './Selection.js'; 6 | import Listing from './Listing.js'; 7 | import mdpath from './../../markdown.js'; 8 | import './styles/Resources.css'; 9 | 10 | function Resources({ match }) { 11 | return ( 12 |
13 |
14 | 15 |
16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 |
24 | item)} 30 | /> 31 |
32 |
33 | ); 34 | } 35 | 36 | export default Resources; 37 | -------------------------------------------------------------------------------- /guides/native/anIntroductionToReason/tableOfContents.md: -------------------------------------------------------------------------------- 1 | #### An Introduction to Reason 2 | 3 | 4 | + [Introduction](/reader/guides/native/anIntroductionToReason/introduction) 5 | + [Get Up & Running](/reader/guides/native/anIntroductionToReason/getUpNRunning) 6 | + [Core Language](/reader/guides/native/anIntroductionToReason/coreLanguage/coreLanguage) 7 | - [Functions](/reader/guides/native/anIntroductionToReason/coreLanguage/functions) 8 | - [Records](/reader/guides/native/anIntroductionToReason/coreLanguage/records) 9 | - [Objects](/reader/guides/native/anIntroductionToReason/coreLanguage/objects) 10 | - [Lists](/reader/guides/native/anIntroductionToReason/coreLanguage/lists) 11 | - [Tuples](/reader/guides/native/anIntroductionToReason/coreLanguage/tuples) 12 | - [Modules](/reader/guides/native/anIntroductionToReason/coreLanguage/modules) 13 | - [Functors](/reader/guides/native/anIntroductionToReason/coreLanguage/functors) 14 | + [Types](/reader/guides/native/anIntroductionToReason/types/types) 15 | - [Reading Types](/reader/guides/native/anIntroductionToReason/types/readingTypes) 16 | - [Type Aliases](/reader/guides/native/anIntroductionToReason/types/typeAliases) 17 | - [Variants](/reader/guides/native/anIntroductionToReason/types/variants) -------------------------------------------------------------------------------- /src/components/Standalone/Navbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Navbar as RNavbar, 4 | Navbrand, 5 | NavItemsLeft, 6 | NavItemsCenter, 7 | NavItemsRight 8 | } from 'rad-navbar'; 9 | import { Link } from 'react-router-dom'; 10 | import Logo from './../../assets/Logo.png'; 11 | import './styles/Navbar.css'; 12 | 13 | function Navbar(props) { 14 | return ( 15 | 16 | 17 |
18 | 19 | 20 | 21 |
22 | 27 | 28 |
29 |

Reason

30 |

Toolchain

31 |

Community

32 |
33 |
34 |
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 |
9 | {technology.map((value, index) => { 10 | if (match.params.technology === value) { 11 | return ( 12 | 19 |

20 | {value 21 | .replace(/([A-Z])/g, ' $1') 22 | .replace(/^./, s => s.toUpperCase())} 23 |

24 | 25 | ); 26 | } 27 | return ( 28 | 33 |

34 | {value 35 | .replace(/([A-Z])/g, ' $1') 36 | .replace(/^./, s => s.toUpperCase())} 37 |

38 | 39 | ); 40 | })} 41 |
42 | ); 43 | } 44 | 45 | export default Selection; 46 | -------------------------------------------------------------------------------- /src/components/Reader/ReaderMenu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Navbar, 4 | Navbrand, 5 | NavItemsLeft, 6 | NavItemsRight, 7 | NavItemsCenter, 8 | NavDrawer 9 | } from 'rad-navbar'; 10 | import { Link } from 'react-router-dom'; 11 | import './styles/ReaderMenu.css'; 12 | import asyncMarkdown from './../Standalone/AsyncMarkdown.js'; 13 | import Edit from './../Standalone/Edit.js'; 14 | import Languages from './../Standalone/Languages.js'; 15 | 16 | function ReaderMenu({category, technology, name, section, title, rr}) { 17 | const Markdown = asyncMarkdown(() => 18 | import(`./../../../${category}/${technology}/${name}/tableOfContents.md`) 19 | .then(module => module, err => console.log(err)) 20 | ); 21 | 22 | return ( 23 | 30 | 31 |
32 | 33 |
34 |
35 | 36 |

{section}

37 |
38 | 39 |

{title}

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 | ![Reason Developer Network](src/assets/banner.png) 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 |
20 |
21 | 22 |
23 | s.toUpperCase())} 27 | section={props.match.params.content 28 | .replace(/([A-Z])/g, ' $1') 29 | .replace(/^./, s => s.toUpperCase())} 30 | category={props.match.params.category} 31 | technology={props.match.params.technology} 32 | name={props.match.params.name} 33 | rr={props.match} 34 | content={props.match.params.content} 35 | /> 36 |
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 |

81 |
82 |
83 |
84 |
85 | ); 86 | } 87 | 88 | export default Home; 89 | -------------------------------------------------------------------------------- /src/components/Resources/Dropdown.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import './styles/Dropdown.css'; 4 | 5 | class Dropdown extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | showMenu: false 10 | }; 11 | } 12 | toggleMenu() { 13 | this.setState(state => ({ 14 | showMenu: !state.showMenu 15 | })); 16 | } 17 | render() { 18 | var categories = ['documentation', 'guides', 'talksAndSlides']; 19 | if (!this.state.showMenu) { 20 | return ( 21 |
22 | this.toggleMenu()} 27 | > 28 |

29 | ▸ 30 | {' '} 31 | {this.props.match.params.category 32 | .replace(/([A-Z])/g, ' $1') 33 | .replace(/^./, s => s.toUpperCase())} 34 |

35 | 36 |
37 | ); 38 | } 39 | return ( 40 |
41 |
42 |
43 | this.toggleMenu()} 48 | > 49 |

50 | ▾ 51 | {' '} 52 | {this.props.match.params.category 53 | .replace(/([A-Z])/g, ' $1') 54 | .replace(/^./, s => s.toUpperCase())} 55 |

56 | 57 |
58 |
59 |
    60 | {categories.reduce( 61 | (acc, curr, index) => { 62 | if (this.props.match.params.category !== curr) { 63 | acc.push( 64 | this.toggleMenu()} 70 | > 71 |
  • 72 |

    73 | {curr 74 | .replace(/([A-Z])/g, ' $1') 75 | .replace(/^./, s => s.toUpperCase())} 76 |

    77 |
  • 78 | 79 | ); 80 | return acc; 81 | } 82 | return acc; 83 | }, 84 | [] 85 | )} 86 |
87 |
88 |
89 |
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 | 6 | 7 | 72 | 73 | 74 | 78 | 82 | 86 | 90 | 94 | 95 | 96 | ); 97 | } 98 | 99 | export default Logo; 100 | --------------------------------------------------------------------------------