Skip to content

Commit 3a8de61

Browse files
glennslaspeddro
andauthored
Nullable additions (#67)
* feat(nullable): add getExn * feat(nullable): add getUnsafe * feat(nullable): add getWithDefault * feat(nullable): add map * feat(nullable): add mapWithDefault * feat(nullable): add flatMap * docs(nullable): add interface * docs(changelog): add changelog entry for Nullable additions * docs(nullable): fix typo x -> value Co-authored-by: Pedro Castro <[email protected]> * feat(nullable/map+flatMap): return value unchanged if null or undefined --------- Co-authored-by: Pedro Castro <[email protected]>
1 parent 0ed37ec commit 3a8de61

File tree

4 files changed

+181
-0
lines changed

4 files changed

+181
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- Remove `Date.valueOf` as it returns the same as `Date.getTime`. https://github.com/rescript-association/rescript-core/pull/61
1818
- Change `Float.fromString` signature. Now accepts only string. https://github.com/rescript-association/rescript-core/pull/54
1919
- Change `Float.parseFloat` signature. Now accepts only string. https://github.com/rescript-association/rescript-core/pull/54
20+
- Add `getExn`, `getUnsafe`, `getWithDefault`, `map`, `mapWithDefault` and `flatMap` to `Nullable`. https://github.com/rescript-association/rescript-core/pull/67
2021

2122
### Documentation
2223

src/Core__Nullable.mjs

+49
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Generated by ReScript, PLEASE EDIT WITH CARE
22

3+
import * as Curry from "rescript/lib/es6/curry.js";
34
import * as Caml_option from "rescript/lib/es6/caml_option.js";
45

56
function fromOption(option) {
@@ -9,7 +10,55 @@ function fromOption(option) {
910

1011
}
1112

13+
function getWithDefault(value, $$default) {
14+
if (value == null) {
15+
return $$default;
16+
} else {
17+
return value;
18+
}
19+
}
20+
21+
function getExn(value) {
22+
if (!(value == null)) {
23+
return value;
24+
}
25+
throw {
26+
RE_EXN_ID: "Invalid_argument",
27+
_1: "Nullable.getExn: value is null or undefined",
28+
Error: new Error()
29+
};
30+
}
31+
32+
function map(value, f) {
33+
if (value == null) {
34+
return value;
35+
} else {
36+
return Curry._1(f, value);
37+
}
38+
}
39+
40+
function mapWithDefault(value, $$default, f) {
41+
if (value == null) {
42+
return $$default;
43+
} else {
44+
return Curry._1(f, value);
45+
}
46+
}
47+
48+
function flatMap(value, f) {
49+
if (value == null) {
50+
return value;
51+
} else {
52+
return Curry._1(f, value);
53+
}
54+
}
55+
1256
export {
1357
fromOption ,
58+
getWithDefault ,
59+
getExn ,
60+
map ,
61+
mapWithDefault ,
62+
flatMap ,
1463
}
1564
/* No side effect */

src/Core__Nullable.res

+32
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,35 @@ let fromOption: option<'a> => t<'a> = option =>
1313
| Some(x) => make(x)
1414
| None => undefined
1515
}
16+
17+
let getWithDefault = (value, default) =>
18+
switch value->toOption {
19+
| Some(x) => x
20+
| None => default
21+
}
22+
23+
let getExn: t<'a> => 'a = value =>
24+
switch value->toOption {
25+
| Some(x) => x
26+
| None => raise(Invalid_argument("Nullable.getExn: value is null or undefined"))
27+
}
28+
29+
external getUnsafe: t<'a> => 'a = "%identity"
30+
31+
let map = (value, f) =>
32+
switch value->toOption {
33+
| Some(x) => make(f(x))
34+
| None => Obj.magic(value)
35+
}
36+
37+
let mapWithDefault = (value, default, f) =>
38+
switch value->toOption {
39+
| Some(x) => f(x)
40+
| None => default
41+
}
42+
43+
let flatMap = (value, f) =>
44+
switch value->toOption {
45+
| Some(x) => f(x)
46+
| None => Obj.magic(value)
47+
}

src/Core__Nullable.resi

+99
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,102 @@ let asNullable = optString->Nullable.fromOption // Nullable.t<string>
8181
```
8282
*/
8383
let fromOption: option<'a> => t<'a>
84+
85+
/**
86+
`getWithDefault(value, default)` returns `value` if not `null` or `undefined`,
87+
otherwise return `default`.
88+
89+
## Examples
90+
91+
```rescript
92+
Nullable.getWithDefault(Nullable.null, "Banana") // Banana
93+
Nullable.getWithDefault(Nulalble.make("Apple"), "Banana") // Apple
94+
95+
let greet = (firstName: option<string>) =>
96+
"Greetings " ++ firstName->Nullable.getWithDefault("Anonymous")
97+
98+
Nullable.make("Jane")->greet // "Greetings Jane"
99+
Nullable.null->greet // "Greetings Anonymous"
100+
```
101+
*/
102+
let getWithDefault: (t<'a>, 'a) => 'a
103+
104+
/**
105+
`getExn(value)` raises an exception if `null` or `undefined`, otherwise returns the value.
106+
107+
```rescript
108+
Nullable.getExn(Nullable.make(3)) // 3
109+
Nullable.getExn(Nullable.null) /* Raises an Error */
110+
```
111+
112+
## Exceptions
113+
114+
- Raises `Invalid_argument` if `value` is `null` or `undefined`
115+
*/
116+
let getExn: t<'a> => 'a
117+
118+
/**
119+
`getUnsafe(value)` returns `value`.
120+
121+
## Examples
122+
123+
```rescript
124+
Nullable.getUnsafe(Nullable.make(3)) == 3
125+
Nullable.getUnsafe(Nullable.null) // Raises an error
126+
```
127+
128+
## Important
129+
130+
- This is an unsafe operation, it assumes `value` is not `null` or `undefined`.
131+
*/
132+
external getUnsafe: t<'a> => 'a = "%identity"
133+
134+
/**
135+
`map(value, f)` returns `f(value)` if `value` is not `null` or `undefined`,
136+
otherwise returns `value` unchanged.
137+
138+
## Examples
139+
140+
```rescript
141+
Nullable.map(Nullable.make(3), x => x * x) // Nullable.make(9)
142+
Nullable.map(Nullable.undefined, x => x * x) // Nullable.undefined
143+
```
144+
*/
145+
let map: (t<'a>, 'a => 'b) => t<'b>
146+
147+
/**
148+
`mapWithDefault(value, default, f)` returns `f(value)` if `value` is not `null`
149+
or `undefined`, otherwise returns `default`.
150+
151+
## Examples
152+
153+
```rescript
154+
let someValue = Nullable.make(3)
155+
someValue->Nullable.mapWithDefault(0, x => x + 5) // 8
156+
157+
let noneValue = Nullable.null
158+
noneValue->Nullable.mapWithDefault(0, x => x + 5) // 0
159+
```
160+
*/
161+
let mapWithDefault: (t<'a>, 'b, 'a => 'b) => 'b
162+
163+
/**
164+
`flatMap(value, f)` returns `f(value)` if `value` is not `null` or `undefined`,
165+
otherwise returns `value` unchanged.
166+
167+
## Examples
168+
169+
```rescript
170+
let addIfAboveOne = value =>
171+
if (value > 1) {
172+
Nullable.make(value + 1)
173+
} else {
174+
Nullable.null
175+
}
176+
177+
Nullable.flatMap(Nullable.make(2), addIfAboveOne) // Nullable.make(3)
178+
Nullable.flatMap(Nullable.make(-4), addIfAboveOne) // Nullable.undefined
179+
Nullable.flatMap(Nullable.null, addIfAboveOne) // Nullable.undefined
180+
```
181+
*/
182+
let flatMap: (t<'a>, 'a => t<'b>) => t<'b>

0 commit comments

Comments
 (0)