概要
この記事では Reason がもつ言語機能のほとんど全てを紹介していきます。 言語機能の詳細な説明ではなく、クイックリファレンスとして機能するようになっています。 各機能の詳細な説明は、左側のガイドをご覧ください。
Let 変数束縛
Details: Let Bindings
機能 | 例 |
---|---|
文字列 | let hi = "Hello World"; |
整数値 | let count = 42; |
型註釈付きでの束縛 | let count: int = 42; |
- Note: Let bindings are immutable and cannot change once created.
組み込み型
Details: Primitives
機能 | Example |
---|---|
整数型 | let x: int = 10; |
浮動小数点数型 | let x: float = 10.0; |
真偽値型 | let x: bool = false; |
文字列型 | let x: string = "ten"; |
文字型 | let x: char = 'c'; |
Unit | let x: unit = (); |
Option | let x: option(int) = Some(10); |
タプル型 | let x: (int, string) = (10, "ten"); |
リスト型 | let x: list(int) = [1, 2, 3]; |
配列型 | let x: array(int) = [|1, 2, 3|]; |
関数型 | let x: (int, int) => int = (a, b) => a + b; |
文字列
Details: Strings
機能 | 例 |
---|---|
文字列 | "Hello" |
文字列の連結 | "Hello " ++ "World" |
文字 | 'x' |
Character at index | let x = "Hello"; x.[2]; |
- String Functions:
module String
数値
機能 | 例 |
---|---|
整数 | 23 , -23 |
整数の演算 | 23 + 1 - 7 * 2 / 5 |
整数の剰余演算 | 13 mod 2 |
浮動小数点数 | 23.0 , -23.0 |
浮動小数点数の四則演算 | 23.0 +. 1.0 -. 7.0 *. 2.0 /. 5.0 |
浮動小数点数の累乗 | 2.0 ** 3.0 |
Booleans and Logical Operators
Details: Boolean
機能 | 例 |
---|---|
真偽値 | true , false |
比較演算 | > , < , >= , <= |
論理演算 | ! , && , || |
参照の等価性 | === , !== |
構造の等価性 | == , != |
If-Else Expressions
機能 | 例 |
---|---|
If-Else expressions | if (condition) { a; } else { b; } |
Ternary expressions | condition ? a : b; |
- Note: These are expressions and can be assigned to a variable:
let x = if (condition) { a; } else { b; };
Functions
Details: Functions
機能 | 例 |
---|---|
Function definition | let divide = (a, b) => a / b; |
Function calls | divide(6, 2); // 3 |
Named arguments | let divide = (~a, ~b) => a / b; |
Calling named arguments | divide(~a=6, ~b=2); // 3 |
Named argument punning | divide(~a, ~b); |
Recursive functions | let rec infinite = () => infinite(); |
Advanced Functions
機能 | 例 |
---|---|
Partial application | let divideTen = divide(10); divideTen(5); // 2 |
Partially applying out of order | let half = divide(_, 2); half(10); // 5 |
Optional arguments | let print = (~prefix=?, text) => {...}; |
Optional arguments with default | let divide = (~a=100, ~b) => a / b; |
Function chaining (pipe) | 32 |> half |> half; // 8 |
Function Types
機能 | 例 |
---|---|
Inline typing | let divide = (a: int, b: int): int => a / b; |
Standalone type | type intFn = (int, int) => int; |
Using standalone type | let divide: intFn = (a, b) => a / b; |
Typing optional arguments | let print = (~prefix: option(string)=?, text) => {...}; |
Implicit Return
There is no return
keyword in Reason. The last expression in a block or function definition is the returned value.
let twentyThree = () => {
let x = 10;
let x = x + 10;
/* x + 3 is the implicit return of the function. */
x + 3;
};
Basic Structures
Details: Basic Structures
Feature | Example |
---|---|
List (Immutable) | [1, 2, 3] |
List add to front | [a1, a2, ...theRest] |
List concat | [a1, a2] @ theRest |
Array (Mutable) | [|1, 2, 3|] |
Array access | let arr = [|1, 2, 3|]; arr[1]; |
Tuples | (1, "hello") |
- List Functions:
module List
- Array Functions:
module Array
Maps and Sets
There are several different ways to interact with Maps and Sets depending on the specific environment being used. In standard Reason code there are Map
and Set
modules:
When using BuckleScript belt
exposes these modules:
There are also other libraries that will provide their own implementation of these data structures. Check the style guide of the project you are working in to determine which module to use.
Type Annotations
Any expression or argument may include a "type annotation". In most cases, type annotations are not necessary and the compiler will infer the types automatically. You may include type annotations to verify your own understanding against what the compiler infers.
Feature | Example |
---|---|
Expression type annotation | let x = (expression: int) |
Annotation on let binding | let x: int = expression; |
Argument/return value annotation | let addOne = (a: int): int => a + 1; |
Type Parameters
Types can be made generic with type parameters.
Feature | Example |
---|---|
Type parameters | type pair('a, 'b) = ('a, 'b); |
Annotation with parameters | let x: pair(int, string) = (10, "ten"); |
String list | let x: list(string) = ["Hello", "World"]; |
Records
Details: Records
Feature | Example |
---|---|
Record definition | type t = {foo: int, bar: string}; |
Record creation | let x = {foo: 10, bar: "hello"}; |
Record access | x.foo; |
Record spread | let y = {...x, bar: "world"}; |
Destructuring | let {foo, bar} = x; |
Mutable record fields | type t = {mutable baz: int}; let z = {baz: 10}; |
Mutable record updates | z.baz = 23; |
With type parameters | type t('a) = {foo: 'a, bar: string}; |
- Note: Record types are nominal. This means that two different record definitions (
type x = {...};
) with the exact same fields are not compatible. They cannot be used interchangeably and cannot be spread into each other.
Variants
Details: Variants
Variant types model values that may assume one of many known variations. This feature is similar to "enums" in other languages, but each variant form may optionally specify data that is carried along with it.
Feature | Example |
---|---|
Variant definition | type t = | Foo | Bar; |
Variants with args | type t = | Foo(string) | Bar(int); |
With type parameters | type t('a) = | One('a) | Two('a, 'a); |
Using a variant | let x = Two("Hello", "World"); |
Options
Details: Options
Options are a built-in variant that represent the presence or absence of a value. It is similar to the concept of "nullable" values in other languages. Options are used often.
Feature | Example |
---|---|
Definition (already defined) | type option('a) = | None | Some('a); |
Value that is present | let x = Some("Hello World"); |
Value that is absent | let y = None; |
Pattern Matching
Pattern matching is a very powerful feature in Reason. It matches against variants and ensures all cases are covered. Start matching using the switch
keyword:
switch (foo) {
| Some(value) => doSomething(value)
| None => error()
}
Feature | Example |
---|---|
Basic case | | Some(value) => doSomething(value) |
When conditions | | Some(value) when value > 10 => doSomething(value) |
Catch-all case | | _ => doSomething() |
Matching lists | | [a, b, ...rest] => doSomething(rest) |
Matching records | | {foo: value} => doSomething(value) |
Matching literals | | "Hello" => handleHello() |
Unit
The special "unit" value (written ()
) represents something that never has any meaningful value (this is distinct from options which may have a value). Functions usually indicate that they perform a side effect by returning a unit value.
Feature | Example |
---|---|
Creating a unit | let x = (); |
Passing to a function | fn(a, b, ()); |
Unit as only argument | let fn = () => 1; fn(); |
Refs
Details: Mutable Bindings
Refs allow mutable "variables" in your program. They are a thin wrapper around a record with a mutable field called contents
.
Feature | Example |
---|---|
Type (already defined) | type ref('a) = {mutable contents: 'a}; |
Ref creation | let x = ref(10); or let x = {contents: 10}; |
Ref access | x^; or x.contents; |
Ref update | x := 20; or x.contents = 20; |
Loops
Details: Loops
Loops are discouraged in most cases. Instead functional programming patterns like map
, filter
, or reduce
can usually be used in their place.
Feature | Example |
---|---|
While | while (condition) {...} |
For (incrementing) | for (i in 0 to 9) {...} (inclusive) |
For (decrementing) | for (i in 9 downto 0) {...} (inclusive) |
- Note: There is no
break
or early returns in Reason. Use a ref containing a bool for break-like behavior:let break = ref(false); while (!break^ && condition) {...};
Modules
Details: Modules
Modules are a way to group types and values. Each Reason file implicitly creates a module of the same name. Each type
definition and let
binding in a module automatically becomes a "member" of that module which can be accessed by other modules. Modules can also be nested using the module
keyword.
Feature | Example |
---|---|
Module creation | module Foo = { let bar = 10; }; |
Module member access | Foo.bar; |
Module types | module type Foo = { let bar: int; }; |
Functors
Functors are like functions that create modules. This is an advanced topic that can be very powerful. Here is a basic example:
module type Stringable = {
type t;
let toString: (t) => string;
};
module Printer = (Item: Stringable) => {
let print = (t: Item.t) => {
print_endline(Item.toString(t));
};
let printList = (list: list(Item.t)) => {
list
|> List.map(Item.toString)
|> String.concat(", ")
|> print_endline;
};
};
module IntPrinter = Printer({
type t = int;
let toString = string_of_int;
});
IntPrinter.print(10); // 10
IntPrinter.printList([1, 2, 3]); // 1, 2, 3
Comments
Feature | Example |
---|---|
Multiline Comment | /* Comment here */ |
Single line Comment | // Comment here |