Skip to content

Commit 1d4073e

Browse files
Add section about extensible variant types. (#211)
* Add section about extensible variant types. * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx remove example notation due to missing constructor * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update pages/docs/manual/latest/extensible-variant.mdx * Update data/sidebar_manual_latest.json * Update pages/docs/manual/latest/extensible-variant.mdx Co-authored-by: Patrick Ecker <[email protected]>
1 parent 3ef9996 commit 1d4073e

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

data/sidebar_manual_latest.json

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
"unboxed",
3434
"reserved-keywords"
3535
],
36+
"Advanced Features": [
37+
"extensible-variant"
38+
],
3639
"JavaScript Interop": [
3740
"interop-cheatsheet",
3841
"embed-raw-javascript",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
title: "Extensible Variant"
3+
description: "Extensible Variants in ReScript"
4+
canonical: "/docs/manual/latest/extensible-variant"
5+
---
6+
7+
# Extensible Variant
8+
9+
Variant types are usually constrained to a fixed set of constructors. There may be very rare cases where you still want to be able to add constructors to a variant type even after its initial type declaration. For this, we offer extensible variant types.
10+
11+
## Definition and Usage
12+
13+
<CodeTab labels={["ReScript", "JS Output"]}>
14+
15+
```res example
16+
type t = ..
17+
18+
type t += Other
19+
20+
type t +=
21+
| Point(float, float)
22+
| Line(float, float, float, float)
23+
```
24+
```js
25+
var Caml_exceptions = require("./stdlib/caml_exceptions.js");
26+
27+
var Other = Caml_exceptions.create("Playground.Other");
28+
29+
var Point = Caml_exceptions.create("Playground.Point");
30+
31+
var Line = Caml_exceptions.create("Playground.Line");
32+
```
33+
34+
</CodeTab>
35+
36+
The `..` in the type declaration above defines an extensible variant `type t`. The `+=` operator is then used to add constructors to the given type.
37+
38+
**Note:** Don't forget the leading `type` keyword when using the `+=` operator!
39+
40+
## Pattern Matching Caveats
41+
42+
Extensible variants are open-ended, so the compiler will not be able to exhaustively pattern match all available cases. You will always need to provide a default `_` case for every `switch` expression.
43+
44+
45+
<CodeTab labels={["ReScript", "JS Output"]}>
46+
47+
48+
```res
49+
let print = v =>
50+
switch v {
51+
| Point(x, y) => Js.log2("Point", (x, y))
52+
| Line(ax, ay, bx, by) => Js.log2("Line", (ax, ay, bx, by))
53+
| Other
54+
| _ => Js.log("Other")
55+
}
56+
```
57+
```js
58+
function print(v) {
59+
if (v.RE_EXN_ID === Point) {
60+
console.log("Point", [v._1, v._2]);
61+
} else if (v.RE_EXN_ID === Line) {
62+
console.log("Line", [v._1, v._2, v._3, v._4]);
63+
} else {
64+
console.log("Other");
65+
}
66+
}
67+
```
68+
69+
</CodeTab>
70+
71+
## Tips & Tricks
72+
73+
**Fun fact:** In ReScript, [exceptions](./exception) are actually extensible variants under the hood, so `exception UserError(string)` is equivalent to `type exn += UserError(string)`. It's one of the very few use-case where extensible variants make sense.
74+
75+
We usually recommend sticking with common [variants](./variant) as much as possible to reap the benefits of exhaustive pattern matching.

0 commit comments

Comments
 (0)