diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e8490e2..9e3d3801 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - Add `panic`/`Error.panic`. https://github.com/rescript-association/rescript-core/pull/72 - The globally available `null` value now originates from `Nullable` and not `Null`, just like the globally available `undefined` value does. https://github.com/rescript-association/rescript-core/pull/88 - Add `Int.range` and `Int.rangeWithOptions`, https://github.com/rescript-association/rescript-core/pull/52 +- Add `flat`, `expect`, and `or` to `Option`, deprecate `orElse`. https://github.com/rescript-association/rescript-core/pull/57 ### Documentation diff --git a/src/Core__Option.mjs b/src/Core__Option.mjs index 29ad429b..d0679d4c 100644 --- a/src/Core__Option.mjs +++ b/src/Core__Option.mjs @@ -2,6 +2,14 @@ import * as Curry from "rescript/lib/es6/curry.js"; import * as Caml_option from "rescript/lib/es6/caml_option.js"; +import * as Core__Error from "./Core__Error.mjs"; + +function flat(opt) { + if (opt !== undefined) { + return Caml_option.valFromOption(opt); + } + +} function filter(opt, p) { var p$1 = Curry.__1(p); @@ -19,9 +27,9 @@ function forEach(opt, f) { } -function getExn(x) { - if (x !== undefined) { - return Caml_option.valFromOption(x); +function getExn(opt) { + if (opt !== undefined) { + return Caml_option.valFromOption(opt); } throw { RE_EXN_ID: "Not_found", @@ -29,6 +37,14 @@ function getExn(x) { }; } +function expect(opt, message) { + if (opt !== undefined) { + return Caml_option.valFromOption(opt); + } else { + return Core__Error.panic(message); + } +} + function mapWithDefault(opt, $$default, f) { var f$1 = Curry.__1(f); if (opt !== undefined) { @@ -62,7 +78,7 @@ function getWithDefault(opt, $$default) { } } -function orElse(opt, other) { +function or(opt, other) { if (opt !== undefined) { return opt; } else { @@ -70,12 +86,12 @@ function orElse(opt, other) { } } -function isSome(x) { - return x !== undefined; +function isSome(opt) { + return opt !== undefined; } -function isNone(x) { - return x === undefined; +function isNone(opt) { + return opt === undefined; } function eq(a, b, f) { @@ -106,14 +122,19 @@ function cmp(a, b, f) { } } +var orElse = or; + export { + flat , filter , forEach , getExn , + expect , mapWithDefault , map , flatMap , getWithDefault , + or , orElse , isSome , isNone , diff --git a/src/Core__Option.res b/src/Core__Option.res index 9b688647..726a074f 100644 --- a/src/Core__Option.res +++ b/src/Core__Option.res @@ -22,73 +22,83 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +let flat = opt => + switch opt { + | Some(v) => v + | None => None + } + let filterU = (opt, p) => switch opt { - | Some(x) as some if p(. x) => some + | Some(value) as some if p(. value) => some | _ => None } -let filter = (opt, p) => filterU(opt, (. x) => p(x)) +let filter = (opt, p) => filterU(opt, (. value) => p(value)) let forEachU = (opt, f) => switch opt { - | Some(x) => f(. x) + | Some(value) => f(. value) | None => () } -let forEach = (opt, f) => forEachU(opt, (. x) => f(x)) +let forEach = (opt, f) => forEachU(opt, (. value) => f(value)) -let getExn = x => - switch x { - | Some(x) => x +let getExn = opt => + switch opt { + | Some(value) => value | None => raise(Not_found) } +let expect = (opt, message) => + switch opt { + | Some(value) => value + | None => Core__Error.panic(message) + } + external getUnsafe: option<'a> => 'a = "%identity" let mapWithDefaultU = (opt, default, f) => switch opt { - | Some(x) => f(. x) + | Some(value) => f(. value) | None => default } -let mapWithDefault = (opt, default, f) => mapWithDefaultU(opt, default, (. x) => f(x)) +let mapWithDefault = (opt, default, f) => mapWithDefaultU(opt, default, (. value) => f(value)) let mapU = (opt, f) => switch opt { - | Some(x) => Some(f(. x)) + | Some(value) => Some(f(. value)) | None => None } -let map = (opt, f) => mapU(opt, (. x) => f(x)) +let map = (opt, f) => mapU(opt, (. value) => f(value)) let flatMapU = (opt, f) => switch opt { - | Some(x) => f(. x) + | Some(value) => f(. value) | None => None } -let flatMap = (opt, f) => flatMapU(opt, (. x) => f(x)) +let flatMap = (opt, f) => flatMapU(opt, (. value) => f(value)) let getWithDefault = (opt, default) => switch opt { - | Some(x) => x + | Some(value) => value | None => default } -let orElse = (opt, other) => +let or = (opt, other) => switch opt { - | Some(_) as some => some + | Some(_) => opt | None => other } -let isSome = x => - switch x { - | Some(_) => true - | None => false - } +let orElse = or + +let isSome = opt => opt !== None -let isNone = x => x == None +let isNone = opt => opt == None let eqU = (a, b, f) => switch a { diff --git a/src/Core__Option.resi b/src/Core__Option.resi index fb3c8a46..2c1f2025 100644 --- a/src/Core__Option.resi +++ b/src/Core__Option.resi @@ -39,6 +39,18 @@ let someString: option = Some("hello") ``` */ +/** +`flat(value)` flattens a nested `option` value to a single level. + +## Examples + +```rescript +Option.flat(Some(Some(10))) // Some(10) +Option.flat(Some(None)) // None +``` +*/ +let flat: option> => option<'a> + /** `filter(opt, f)` applies `f` to `opt`, if `f` returns `true`, then it returns `Some(value)`, otherwise returns `None`. @@ -66,7 +78,7 @@ Option.forEach(None, x => Console.log(x)) // returns () let forEach: (option<'a>, 'a => unit) => unit /** -`getExn(opt)` returns `value` if `opt` is `Some(value)`, otherwise raises an exception. +`getExn(opt)` returns `value` if `opt` is `Some(value)`, raises `Not_found` if `None`. ```rescript Option.getExn(Some(3)) // 3 @@ -75,10 +87,24 @@ Option.getExn(None) /* Raises an Error */ ## Exceptions -- Raises an error if `opt` is `None` +- Raises `Not_found` if `opt` is `None` */ let getExn: option<'a> => 'a +/** +`expect(opt, message)` returns `value` if `Some(value)`, raises a `Failure` expection with the given message if `None`. + +```rescript +Option.expect(Some(3), "should not be None") // 3 +Option.expect(None, "should not be None") // Raises `Failure("should not be None")` +``` + +## Exceptions + +- Panics if `opt` is `None` +*/ +let expect: (option<'a>, string) => 'a + /** `getUnsafe(value)` returns `value`. @@ -89,9 +115,9 @@ Option.getUnsafe(Some(3)) == 3 Option.getUnsafe(None) // Raises an error ``` -## Exceptions +## Important -- This is an unsafe operation, it assumes `value` is neither `None` nor `Some(None(...)))` +This is an unsafe operation, it assumes `value` is neither `None`, `Some(None))`, `Some(Some(None))` etc. */ external getUnsafe: option<'a> => 'a = "%identity" @@ -160,6 +186,19 @@ None->greet // "Greetings Anonymous" */ let getWithDefault: (option<'a>, 'a) => 'a +/** +`or(opt1, opt2)` returns `opt2` if `opt1` is `None`, otherwise `opt1`. + +## Examples + +```rescript +Option.or(Some(1812), Some(1066)) == Some(1812) +Option.or(None, Some(1066) == Some(1066) +Option.or(None, None) == None +``` +*/ +let or: (option<'a>, option<'a>) => option<'a> + /** `orElse(opt1, opt2)` returns `opt2` if `opt1` is `None`, otherwise `opt1`. @@ -171,6 +210,7 @@ Option.orElse(None, Some(1066) == Some(1066) Option.orElse(None, None) == None ``` */ +@deprecated("Use `or` instead") let orElse: (option<'a>, option<'a>) => option<'a> /**