diff --git a/CHANGELOG.md b/CHANGELOG.md index 99fe1e50..8b5fe554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Remove `Date.valueOf` as it returns the same as `Date.getTime`. https://github.com/rescript-association/rescript-core/pull/61 - Change `Float.fromString` signature. Now accepts only string. https://github.com/rescript-association/rescript-core/pull/54 - Change `Float.parseFloat` signature. Now accepts only string. https://github.com/rescript-association/rescript-core/pull/54 +- Add `getExn`, `getUnsafe`, `getWithDefault`, `map`, `mapWithDefault` and `flatMap` to `Nullable`. https://github.com/rescript-association/rescript-core/pull/67 ### Documentation diff --git a/src/Core__Nullable.mjs b/src/Core__Nullable.mjs index bdc0e58c..1a7b1ff3 100644 --- a/src/Core__Nullable.mjs +++ b/src/Core__Nullable.mjs @@ -1,5 +1,6 @@ // Generated by ReScript, PLEASE EDIT WITH CARE +import * as Curry from "rescript/lib/es6/curry.js"; import * as Caml_option from "rescript/lib/es6/caml_option.js"; function fromOption(option) { @@ -9,7 +10,55 @@ function fromOption(option) { } +function getWithDefault(value, $$default) { + if (value == null) { + return $$default; + } else { + return value; + } +} + +function getExn(value) { + if (!(value == null)) { + return value; + } + throw { + RE_EXN_ID: "Invalid_argument", + _1: "Nullable.getExn: value is null or undefined", + Error: new Error() + }; +} + +function map(value, f) { + if (value == null) { + return value; + } else { + return Curry._1(f, value); + } +} + +function mapWithDefault(value, $$default, f) { + if (value == null) { + return $$default; + } else { + return Curry._1(f, value); + } +} + +function flatMap(value, f) { + if (value == null) { + return value; + } else { + return Curry._1(f, value); + } +} + export { fromOption , + getWithDefault , + getExn , + map , + mapWithDefault , + flatMap , } /* No side effect */ diff --git a/src/Core__Nullable.res b/src/Core__Nullable.res index 044a037b..0d74399a 100644 --- a/src/Core__Nullable.res +++ b/src/Core__Nullable.res @@ -13,3 +13,35 @@ let fromOption: option<'a> => t<'a> = option => | Some(x) => make(x) | None => undefined } + +let getWithDefault = (value, default) => + switch value->toOption { + | Some(x) => x + | None => default + } + +let getExn: t<'a> => 'a = value => + switch value->toOption { + | Some(x) => x + | None => raise(Invalid_argument("Nullable.getExn: value is null or undefined")) + } + +external getUnsafe: t<'a> => 'a = "%identity" + +let map = (value, f) => + switch value->toOption { + | Some(x) => make(f(x)) + | None => Obj.magic(value) + } + +let mapWithDefault = (value, default, f) => + switch value->toOption { + | Some(x) => f(x) + | None => default + } + +let flatMap = (value, f) => + switch value->toOption { + | Some(x) => f(x) + | None => Obj.magic(value) + } diff --git a/src/Core__Nullable.resi b/src/Core__Nullable.resi index 41345eb4..8037cdac 100644 --- a/src/Core__Nullable.resi +++ b/src/Core__Nullable.resi @@ -81,3 +81,102 @@ let asNullable = optString->Nullable.fromOption // Nullable.t ``` */ let fromOption: option<'a> => t<'a> + +/** +`getWithDefault(value, default)` returns `value` if not `null` or `undefined`, +otherwise return `default`. + +## Examples + +```rescript +Nullable.getWithDefault(Nullable.null, "Banana") // Banana +Nullable.getWithDefault(Nulalble.make("Apple"), "Banana") // Apple + +let greet = (firstName: option) => + "Greetings " ++ firstName->Nullable.getWithDefault("Anonymous") + +Nullable.make("Jane")->greet // "Greetings Jane" +Nullable.null->greet // "Greetings Anonymous" +``` +*/ +let getWithDefault: (t<'a>, 'a) => 'a + +/** +`getExn(value)` raises an exception if `null` or `undefined`, otherwise returns the value. + +```rescript +Nullable.getExn(Nullable.make(3)) // 3 +Nullable.getExn(Nullable.null) /* Raises an Error */ +``` + +## Exceptions + +- Raises `Invalid_argument` if `value` is `null` or `undefined` +*/ +let getExn: t<'a> => 'a + +/** +`getUnsafe(value)` returns `value`. + +## Examples + +```rescript +Nullable.getUnsafe(Nullable.make(3)) == 3 +Nullable.getUnsafe(Nullable.null) // Raises an error +``` + +## Important + +- This is an unsafe operation, it assumes `value` is not `null` or `undefined`. +*/ +external getUnsafe: t<'a> => 'a = "%identity" + +/** +`map(value, f)` returns `f(value)` if `value` is not `null` or `undefined`, +otherwise returns `value` unchanged. + +## Examples + +```rescript +Nullable.map(Nullable.make(3), x => x * x) // Nullable.make(9) +Nullable.map(Nullable.undefined, x => x * x) // Nullable.undefined +``` +*/ +let map: (t<'a>, 'a => 'b) => t<'b> + +/** +`mapWithDefault(value, default, f)` returns `f(value)` if `value` is not `null` +or `undefined`, otherwise returns `default`. + +## Examples + +```rescript +let someValue = Nullable.make(3) +someValue->Nullable.mapWithDefault(0, x => x + 5) // 8 + +let noneValue = Nullable.null +noneValue->Nullable.mapWithDefault(0, x => x + 5) // 0 +``` +*/ +let mapWithDefault: (t<'a>, 'b, 'a => 'b) => 'b + +/** +`flatMap(value, f)` returns `f(value)` if `value` is not `null` or `undefined`, +otherwise returns `value` unchanged. + +## Examples + +```rescript +let addIfAboveOne = value => + if (value > 1) { + Nullable.make(value + 1) + } else { + Nullable.null + } + +Nullable.flatMap(Nullable.make(2), addIfAboveOne) // Nullable.make(3) +Nullable.flatMap(Nullable.make(-4), addIfAboveOne) // Nullable.undefined +Nullable.flatMap(Nullable.null, addIfAboveOne) // Nullable.undefined +``` +*/ +let flatMap: (t<'a>, 'a => t<'b>) => t<'b>