I’m trying to convert Js.Json.parseExn
into a Belt.Result
I’ve tried switching, but I can’t seem to get any of the pattern matching for errors to work; it keeps thinking it’s getting a Js.Json.t back, but there is a lurking SyntaxError from JS. I’ve tried various try catch formatting, but can’t seem to get it.
I just want something like:
let saferParsingOfJSON = string =>
switch Js.Json.parseExn(string) {
| json => Belt.Result.Ok(json)
| _ => Belt.Result.Error("cow")
}
The above doesn’t work, and I don’t like the _
; I’d love to get info on what type of error it is, and get access to the error message.
… er… wait, this works:
let saferParsingOfJSON = string =>
switch Js.Json.parseExn(string) {
| json => Belt.Result.Ok(json)
| exception _ => Belt.Result.Error("cow")
}
:: tries again ::
Holy crap, coffee is amazing.
let messageFromJavaScriptError = error =>
switch error {
| exception error => {
let optError: option<Js.Exn.t> = Js.Exn.asJsExn(error)
switch optError {
| Some(error) =>
switch Js.Exn.message(error) {
| None => None
| Some(errorMessage) => Some(errorMessage)
}
| None => None
}
}
| _ => None
}
let saferParsingOfJSON = string =>
switch Js.Json.parseExn(string) {
| json => Belt.Result.Ok(json)
| exception err => Belt.Result.Error(Js.Option.getWithDefault("no clue", messageFromJavaScriptError(err)))
}
Hrm… I still can’t quite get at the JavaScript specific exception. I’ve tried putting this in the middle of the messageFromJavaScriptError
function above:
| Js.Exn.Error(obj) =>
switch Js.Exn.message(obj) {
| Some(m) => Some(m)
| None => None
}
But then other functions that pass in Js.Promise error’s don’t work with that switch.
Ok, I think I finally figured it out (for real this time). I changed the parsing to be:
let safeParse = string =>
try {
let json = Js.Json.parseExn(string)
Belt.Result.Ok(json)
} catch {
| Js.Exn.Error(obj) =>
switch Js.Exn.message(obj) {
| Some(m) => Belt.Result.Error(m)
| None => Belt.Result.Error("Unknown")
}
}
And that’ll return a result that has the JavaScript exception error string. Geez, I need some sleep.
Btw, Ok
and Error
are builtins, you can just do Ok(...)
and Error(...)
. Belt.Result
module just re-exports them.
2 Likes
Dude, that’s awesome, 2 follow ups now…
Is there a list of these built ins? Like, where the heck is failWith
documented, lol.
How can I shorten 'em. Like instead of Js.Option.thing
why can’t I go let Option = Js.Option
? Is there a way to do something like that to remove the Belt or Js prefix to shorten things?
Those built-ins are not documented in one place, some of them live in different places of docs and some of them are not documented.
you can alias module names like this
module Option = Belt.Option
another way to get Option
in scope is to open Belt
open Belt
let x = Some(2) -> Option.map(x => x*2)
you can also bring some items in scope with pattern matching on packed module
let {map, keep} = module(Belt.Option)
3 Likes
Dude, #1 is exactly what I’ve needed all my ReScript Life®, thank you so much!
johnj
June 10, 2021, 5:12pm
9
I don’t think they’re in the ReScript documentation (yet) but they’re inherited from OCaml. You can see them (in OCaml syntax) on those docs. ReScript is currently based on OCaml 4.06.
https://www.ocaml.org/releases/4.06/htmlman/libref/Pervasives.html
https://www.ocaml.org/releases/4.06/htmlman/core.html
Note that there are a few differences between those docs and what ReScript supports, but most of it should be the same.
1 Like
spyder
June 11, 2021, 2:59am
10
This can be shortened to:
let safeParse = string =>
switch Js.Json.parseExn(string) {
| json => Ok(json)
| exception Js.Exn.Error(exn) =>
exn->Js.Exn.message->Belt.Option.getWithDefault("Unknown")->Error
}
4 Likes