From a5d3e5d5f70d817025b0db494caf52587c1f4862 Mon Sep 17 00:00:00 2001 From: glennsl Date: Sat, 25 Feb 2023 14:14:23 +0100 Subject: [PATCH 1/4] feat(null): add getWithDefault, getExn, getUnsafe, map, mapWithDefault, flatMap --- src/Core__Null.mjs | 49 ++++++++++++++++++++++ src/Core__Null.res | 32 +++++++++++++++ src/Core__Null.resi | 99 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) diff --git a/src/Core__Null.mjs b/src/Core__Null.mjs index 9bbfc49d..18551f8f 100644 --- a/src/Core__Null.mjs +++ b/src/Core__Null.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) { @@ -10,7 +11,55 @@ function fromOption(option) { } } +function getWithDefault(value, $$default) { + if (value !== null) { + return value; + } else { + return $$default; + } +} + +function getExn(value) { + if (value !== null) { + return value; + } + throw { + RE_EXN_ID: "Invalid_argument", + _1: "Null.getExn: value is null", + Error: new Error() + }; +} + +function map(value, f) { + if (value !== null) { + return Curry._1(f, value); + } else { + return null; + } +} + +function mapWithDefault(value, $$default, f) { + if (value !== null) { + return Curry._1(f, value); + } else { + return $$default; + } +} + +function flatMap(value, f) { + if (value !== null) { + return Curry._1(f, value); + } else { + return null; + } +} + export { fromOption , + getWithDefault , + getExn , + map , + mapWithDefault , + flatMap , } /* No side effect */ diff --git a/src/Core__Null.res b/src/Core__Null.res index 2b9c0c9e..3fca7268 100644 --- a/src/Core__Null.res +++ b/src/Core__Null.res @@ -13,3 +13,35 @@ let fromOption: option<'a> => t<'a> = option => | Some(x) => make(x) | None => null } + +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("Null.getExn: value is null")) + } + +external getUnsafe: t<'a> => 'a = "%identity" + +let map = (value, f) => + switch value->toOption { + | Some(x) => make(f(x)) + | None => null + } + +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 => null + } diff --git a/src/Core__Null.resi b/src/Core__Null.resi index 989c9f3b..ffc1df9b 100644 --- a/src/Core__Null.resi +++ b/src/Core__Null.resi @@ -71,3 +71,102 @@ Console.log(asNull == Null.null) // Logs `true` to the console. ``` */ let fromOption: option<'a> => t<'a> + +/** +`getWithDefault(value, default)` returns `value` if not `null`, otherwise return +`default`. + +## Examples + +```rescript +Null.getWithDefault(Null.null, "Banana") // Banana +Null.getWithDefault(Nulalble.make("Apple"), "Banana") // Apple + +let greet = (firstName: option) => + "Greetings " ++ firstName->Null.getWithDefault("Anonymous") + +Null.make("Jane")->greet // "Greetings Jane" +Null.null->greet // "Greetings Anonymous" +``` +*/ +let getWithDefault: (t<'a>, 'a) => 'a + +/** +`getExn(value)` raises an exception if `null`, otherwise returns the value. + +```rescript +Null.getExn(Null.make(3)) // 3 +Null.getExn(Null.null) /* Raises an Error */ +``` + +## Exceptions + +- Raises `Invalid_argument` if `value` is `null`, +*/ +let getExn: t<'a> => 'a + +/** +`getUnsafe(value)` returns `value`. + +## Examples + +```rescript +Null.getUnsafe(Null.make(3)) == 3 +Null.getUnsafe(Null.null) // Raises an error +``` + +## Important + +- This is an unsafe operation, it assumes `value` is not `null`. +*/ +external getUnsafe: t<'a> => 'a = "%identity" + +/** +`map(value, f)` returns `f(value)` if `value` is not `null`, otherwise returns +`value` unchanged. + +## Examples + +```rescript +Null.map(Null.make(3), x => x * x) // Null.make(9) +Null.map(Null.null, x => x * x) // Null.null +``` +*/ +let map: (t<'a>, 'a => 'b) => t<'b> + +/** +`mapWithDefault(value, default, f)` returns `f(value)` if `value` is not `null`, +otherwise returns `default`. + +## Examples + +```rescript +let someValue = Null.make(3) +someValue->Null.mapWithDefault(0, x => x + 5) // 8 + +let noneValue = Null.null +noneValue->Null.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`, otherwise +returns `value` unchanged. + +## Examples + +```rescript +let addIfAboveOne = value => + if (value > 1) { + Null.make(value + 1) + } else { + Null.null + } + +Null.flatMap(Null.make(2), addIfAboveOne) // Null.make(3) +Null.flatMap(Null.make(-4), addIfAboveOne) // Null.null +Null.flatMap(Null.null, addIfAboveOne) // Null.null +``` +*/ +let flatMap: (t<'a>, 'a => t<'b>) => t<'b> From 54998fcaf4ce78ba67b07496513cddd835ac925b Mon Sep 17 00:00:00 2001 From: glennsl Date: Sat, 25 Feb 2023 14:16:17 +0100 Subject: [PATCH 2/4] docs(null): Null.null -> null --- src/Core__Null.resi | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Core__Null.resi b/src/Core__Null.resi index ffc1df9b..f6d2bd51 100644 --- a/src/Core__Null.resi +++ b/src/Core__Null.resi @@ -27,7 +27,7 @@ See [`null`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/O ## Examples ```rescript -Console.log(Null.null) // Logs `null` to the console. +Console.log(null) // Logs `null` to the console. ``` */ external null: t<'a> = "#null" @@ -67,7 +67,7 @@ Turns an `option` into a `Null.t`. `None` will be converted to `null`. ```rescript let optString: option = None let asNull = optString->Null.fromOption // Null.t -Console.log(asNull == Null.null) // Logs `true` to the console. +Console.log(asNull == null) // Logs `true` to the console. ``` */ let fromOption: option<'a> => t<'a> @@ -79,14 +79,14 @@ let fromOption: option<'a> => t<'a> ## Examples ```rescript -Null.getWithDefault(Null.null, "Banana") // Banana +Null.getWithDefault(null, "Banana") // Banana Null.getWithDefault(Nulalble.make("Apple"), "Banana") // Apple let greet = (firstName: option) => "Greetings " ++ firstName->Null.getWithDefault("Anonymous") Null.make("Jane")->greet // "Greetings Jane" -Null.null->greet // "Greetings Anonymous" +null->greet // "Greetings Anonymous" ``` */ let getWithDefault: (t<'a>, 'a) => 'a @@ -96,7 +96,7 @@ let getWithDefault: (t<'a>, 'a) => 'a ```rescript Null.getExn(Null.make(3)) // 3 -Null.getExn(Null.null) /* Raises an Error */ +Null.getExn(null) /* Raises an Error */ ``` ## Exceptions @@ -112,7 +112,7 @@ let getExn: t<'a> => 'a ```rescript Null.getUnsafe(Null.make(3)) == 3 -Null.getUnsafe(Null.null) // Raises an error +Null.getUnsafe(null) // Raises an error ``` ## Important @@ -129,7 +129,7 @@ external getUnsafe: t<'a> => 'a = "%identity" ```rescript Null.map(Null.make(3), x => x * x) // Null.make(9) -Null.map(Null.null, x => x * x) // Null.null +Null.map(null, x => x * x) // null ``` */ let map: (t<'a>, 'a => 'b) => t<'b> @@ -144,7 +144,7 @@ otherwise returns `default`. let someValue = Null.make(3) someValue->Null.mapWithDefault(0, x => x + 5) // 8 -let noneValue = Null.null +let noneValue = null noneValue->Null.mapWithDefault(0, x => x + 5) // 0 ``` */ @@ -161,12 +161,12 @@ let addIfAboveOne = value => if (value > 1) { Null.make(value + 1) } else { - Null.null + null } Null.flatMap(Null.make(2), addIfAboveOne) // Null.make(3) -Null.flatMap(Null.make(-4), addIfAboveOne) // Null.null -Null.flatMap(Null.null, addIfAboveOne) // Null.null +Null.flatMap(Null.make(-4), addIfAboveOne) // null +Null.flatMap(null, addIfAboveOne) // null ``` */ let flatMap: (t<'a>, 'a => t<'b>) => t<'b> From daf09ae02f72bf9dba112dab1a1f58b3f67533b6 Mon Sep 17 00:00:00 2001 From: glennsl Date: Sat, 25 Feb 2023 14:17:33 +0100 Subject: [PATCH 3/4] docs(nullable): Nullable.undefined -> undefined --- src/Core__Nullable.resi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Core__Nullable.resi b/src/Core__Nullable.resi index 8037cdac..8df01762 100644 --- a/src/Core__Nullable.resi +++ b/src/Core__Nullable.resi @@ -29,7 +29,7 @@ See [`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refere ## Examples ```rescript -Console.log(Nullable.undefined) // Logs `undefined` to the console. +Console.log(undefined) // Logs `undefined` to the console. ``` */ external undefined: t<'a> = "#undefined" @@ -139,7 +139,7 @@ otherwise returns `value` unchanged. ```rescript Nullable.map(Nullable.make(3), x => x * x) // Nullable.make(9) -Nullable.map(Nullable.undefined, x => x * x) // Nullable.undefined +Nullable.map(undefined, x => x * x) // undefined ``` */ let map: (t<'a>, 'a => 'b) => t<'b> @@ -175,8 +175,8 @@ let addIfAboveOne = value => } Nullable.flatMap(Nullable.make(2), addIfAboveOne) // Nullable.make(3) -Nullable.flatMap(Nullable.make(-4), addIfAboveOne) // Nullable.undefined -Nullable.flatMap(Nullable.null, addIfAboveOne) // Nullable.undefined +Nullable.flatMap(Nullable.make(-4), addIfAboveOne) // undefined +Nullable.flatMap(Nullable.null, addIfAboveOne) // undefined ``` */ let flatMap: (t<'a>, 'a => t<'b>) => t<'b> From 8030cdbd34a82e65f836cb8306bf5f4e7020f37e Mon Sep 17 00:00:00 2001 From: glennsl Date: Sat, 25 Feb 2023 14:21:11 +0100 Subject: [PATCH 4/4] docs(changelog): add changelog entry for Null additions --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b5fe554..cc992beb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - 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 +- Add `getExn`, `getUnsafe`, `getWithDefault`, `map`, `mapWithDefault` and `flatMap` to `Null`. https://github.com/rescript-association/rescript-core/pull/73 ### Documentation