diff --git a/CHANGELOG.md b/CHANGELOG.md index 5df9f6b0..d02ccbea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Next version +### API changes + +- Add `Option.isNoneOr` and `Option.isSomeAnd` https://github.com/rescript-association/rescript-core/pull/124 + ## 0.4.0 ### API changes diff --git a/src/Core__Option.mjs b/src/Core__Option.mjs index 455655f8..64284145 100644 --- a/src/Core__Option.mjs +++ b/src/Core__Option.mjs @@ -104,6 +104,22 @@ function compare(a, b, cmp) { } } +function isSomeAnd(o, p) { + if (o !== undefined) { + return Curry._1(p, Caml_option.valFromOption(o)); + } else { + return false; + } +} + +function isNoneOr(o, p) { + if (o !== undefined) { + return Curry._1(p, Caml_option.valFromOption(o)); + } else { + return true; + } +} + export { filter , forEach , @@ -117,5 +133,7 @@ export { isNone , equal , compare , + isSomeAnd , + isNoneOr , } /* No side effect */ diff --git a/src/Core__Option.res b/src/Core__Option.res index bc181ded..b4cfd992 100644 --- a/src/Core__Option.res +++ b/src/Core__Option.res @@ -104,3 +104,15 @@ let compare = (a, b, cmp) => | (Some(_), None) => Core__Ordering.greater | (None, None) => Core__Ordering.equal } + +let isSomeAnd = (o, p) => + switch o { + | None => false + | Some(v) => p(v) + } + +let isNoneOr = (o, p) => + switch o { + | None => true + | Some(v) => p(v) + } diff --git a/src/Core__Option.resi b/src/Core__Option.resi index 8ab0abec..2ec5eb87 100644 --- a/src/Core__Option.resi +++ b/src/Core__Option.resi @@ -248,3 +248,33 @@ compare(None, None, clockCompare) // 0. ``` */ let compare: (option<'a>, option<'b>, ('a, 'b) => Core__Ordering.t) => Core__Ordering.t + +/** +`isSomeAnd(option, predicate)` tests whether the option is `Some` **and** the predicate applied to its value is true. + +An option can be thought of as an array with 0 or 1 items in it. `isSomeAnd` is similar to `Array.some` and acts like the "there exists" quantifier in mathematics. It returns false for a `None` option. + +## Examples + +```rescript +Option.isSomeAnd(None, i => i >= 0) // false +Option.isSomeAnd(Some(3), i => i > 1) // true +Option.isSomeAnd(Some(3), i => i < 0) // false +``` +*/ +let isSomeAnd: (option<'a>, 'a => bool) => bool + +/** +`isNoneOr(option, predicate)` tests whether the option is `None` **or** the predicate applied to its value is true. + +An option can be thought of as an array with 0 or 1 items in it. `isNoneOr` is similar to `Array.every` and acts like the "for all" quantifier in mathematics. In particular it returns true when the option is `None`. + +## Examples + +```rescript +Option.isNoneOr(None, i => i >= 0) // true +Option.isNoneOr(Some(3), i => i > 1) // true +Option.isNoneOr(Some(3), i => i < 0) // false +``` +*/ +let isNoneOr: (option<'a>, 'a => bool) => bool diff --git a/test/OptionTests.mjs b/test/OptionTests.mjs new file mode 100644 index 00000000..eff1071f --- /dev/null +++ b/test/OptionTests.mjs @@ -0,0 +1,77 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Test from "./Test.mjs"; +import * as Caml_obj from "rescript/lib/es6/caml_obj.js"; +import * as Core__Option from "../src/Core__Option.mjs"; + +var eq = Caml_obj.equal; + +function isPositive(i) { + return i > 0; +} + +Test.run([ + [ + "OptionTests.res", + 12, + 13, + 47 + ], + "isSomeAnd: if None, return false" + ], Core__Option.isSomeAnd(undefined, isPositive), eq, false); + +Test.run([ + [ + "OptionTests.res", + 19, + 13, + 55 + ], + "isSomeAnd: if Some and true, return true" + ], Core__Option.isSomeAnd(1, isPositive), eq, true); + +Test.run([ + [ + "OptionTests.res", + 25, + 13, + 57 + ], + "isSomeAnd: if Some and false, return false" + ], Core__Option.isSomeAnd(-1, isPositive), eq, false); + +Test.run([ + [ + "OptionTests.res", + 31, + 20, + 52 + ], + "isNoneOr: if None, return true" + ], Core__Option.isNoneOr(undefined, isPositive), eq, true); + +Test.run([ + [ + "OptionTests.res", + 33, + 13, + 54 + ], + "isNoneOr: if Some and true, return true" + ], Core__Option.isNoneOr(1, isPositive), eq, true); + +Test.run([ + [ + "OptionTests.res", + 39, + 13, + 56 + ], + "isNoneOr: if Some and false, return false" + ], Core__Option.isNoneOr(-1, isPositive), eq, false); + +export { + eq , + isPositive , +} +/* Not a pure module */ diff --git a/test/OptionTests.res b/test/OptionTests.res new file mode 100644 index 00000000..6e8dd4e7 --- /dev/null +++ b/test/OptionTests.res @@ -0,0 +1,43 @@ +open RescriptCore + +let eq = (a, b) => a == b + +// ====================== +// isSomeAnd and isNoneOr +// ====================== + +let isPositive = i => i > 0 + +Test.run( + __POS_OF__("isSomeAnd: if None, return false"), + None->Option.isSomeAnd(isPositive), + eq, + false, +) + +Test.run( + __POS_OF__("isSomeAnd: if Some and true, return true"), + Some(1)->Option.isSomeAnd(isPositive), + eq, + true, +) +Test.run( + __POS_OF__("isSomeAnd: if Some and false, return false"), + Some(-1)->Option.isSomeAnd(isPositive), + eq, + false, +) + +Test.run(__POS_OF__("isNoneOr: if None, return true"), None->Option.isNoneOr(isPositive), eq, true) +Test.run( + __POS_OF__("isNoneOr: if Some and true, return true"), + Some(1)->Option.isNoneOr(isPositive), + eq, + true, +) +Test.run( + __POS_OF__("isNoneOr: if Some and false, return false"), + Some(-1)->Option.isNoneOr(isPositive), + eq, + false, +) diff --git a/test/TestSuite.mjs b/test/TestSuite.mjs index 3d8e7128..918ee960 100644 --- a/test/TestSuite.mjs +++ b/test/TestSuite.mjs @@ -4,6 +4,7 @@ import * as IntTests from "./IntTests.mjs"; import * as TestTests from "./TestTests.mjs"; import * as ArrayTests from "./ArrayTests.mjs"; import * as ErrorTests from "./ErrorTests.mjs"; +import * as OptionTests from "./OptionTests.mjs"; import * as PromiseTest from "./PromiseTest.mjs"; import * as ResultTests from "./ResultTests.mjs"; import * as TypedArrayTests from "./TypedArrayTests.mjs"; @@ -34,8 +35,6 @@ var forEachIfOkCallFunction = ResultTests.forEachIfOkCallFunction; var forEachIfErrorDoNotCallFunction = ResultTests.forEachIfErrorDoNotCallFunction; -var eq = TypedArrayTests.eq; - var num1 = TypedArrayTests.num1; var num2 = TypedArrayTests.num2; @@ -50,6 +49,10 @@ var areSame = TypedArrayTests.areSame; var o = TypedArrayTests.o; +var eq = OptionTests.eq; + +var isPositive = OptionTests.isPositive; + export { bign , TestError , @@ -64,7 +67,6 @@ export { $$catch , forEachIfOkCallFunction , forEachIfErrorDoNotCallFunction , - eq , num1 , num2 , num3 , @@ -72,5 +74,7 @@ export { assertWillThrow , areSame , o , + eq , + isPositive , } /* IntTests Not a pure module */ diff --git a/test/TestSuite.res b/test/TestSuite.res index 18bd6273..2cdf2b6a 100644 --- a/test/TestSuite.res +++ b/test/TestSuite.res @@ -5,3 +5,4 @@ include ArrayTests include IntTests include ResultTests include TypedArrayTests +include OptionTests