Thank you @theScottyJam for the many cases discussed, below are some of my thoughts:
- For immutable
I think the immutable one should not be included in this proposal, the case is more widely affected than Maybe itself, and make things more complex.
- For null and error handling
The Maybe(null).unwrap()
always throw a e: MaybeError
, and the e.value
will be Maybe.none
, and the actual value of Maybe.none
should be discussed, maybe it's just the same as null
, but using it can be more semantical for programmers, that to say: "Hey it's unhealthy and have empty error value: none".
The null
semantic in Maybe
is an empty error (but it is an error).
And Maybe
also want to let JS code more friendly to try...catch
to avoid using it, and led to rust way of error handling using ?
(here we use !
), by nested Maybe
, that is, One thing is maybe, all parents affected will become Maybe
, that way, will led to have more elegant way to handle errors than many try...catch
.
I think using !
to handle the error is better than rust ?
, is that !
is lazy
(later binding when used), and the error produced by Maybe
will not immediately return, so have a chance to let user handle it in the same function scope.
Think below code:
function getUserName(url) : Maybe<String, NetworkError> {
const user = maybeGetUser(url);
return Maybe(user!.name)
}
The !
is syntax sugar of unwrap
, so if cannot unwrap, error type should be NetworkError
(DownState), else you get String
type name
(UpState).
Instead, the try..catch
way:
function getUserName(url) : String | null {
let user
try{
user = getUser(url);
return user.name
}catch(e){
console.log(e.message)
throw e
}
}
The above code:
- Not elegant, too much boilerplate for error handling all the place.
- The return value is largely user defined (e.g., it's also may return an object to hold the NetworkError), people have to lookup the signature constantly to know the API, but hard to know what's errors will be thrown.
For the Maybe
version:
- More semantic and elegant.
- People know there's some errors maybe, like Java's
function throws
keyword does, the error message in the level of language, one pattern for many.
- The caller should handle the errors, and stop return
Maybe
, or handle it then wrap it in another Maybe
to let parents know it is a maybe.
- For .else
hold an error
If the .else
hold an error, it's indeed bad practice but if it has semantic to user, like Maybe<UseInfoError, NetworkError>
, it's up to user to decide the semantic, cannot be defined in the proposal, but that led to a topic: Error
as UpState
, I think that case should also be deeply discussed also.