class Thing { | |
val = null; | |
constructor(val) { | |
this.val = val; | |
} | |
unwrap() { | |
throw "unimplemented!"; | |
} | |
is_ok() { | |
throw "unimplemented!"; | |
} | |
is_err() { | |
throw "unimplemented!"; | |
} | |
} | |
export class Ok extends Thing { | |
unwrap = () => this.val; | |
is_ok = () => true; | |
is_err = () => false; | |
} | |
export class Err extends Thing { | |
unwrap = () => throw this.val; | |
is_ok = () => false; | |
is_err = () => true; | |
} | |
export class Result { | |
val = null; | |
constructor(val) { | |
this.val = val | |
} | |
and(val) { | |
if(this.val.is_ok() && val.is_ok()) { | |
return new Result(val); | |
} else { | |
if(this.val.is_err()) { | |
return new Result(this.val); | |
} else if(val.is_err()) { | |
return new Result(val); | |
} | |
} | |
} | |
and_then(cb) { | |
if(this.val.is_ok()) { | |
return cb(this.val); | |
} else { | |
return new Result(this.val) | |
} | |
} | |
or(val) { | |
if(this.val.is_ok()) { | |
return new Result(this.val); | |
} else { | |
return new Result(val); | |
} | |
} | |
unwrap() { | |
return this.val.unwrap(); | |
} | |
static async try(promise) { | |
try { | |
return new Result(new Ok(await promise)); | |
} catch(e) { | |
return new Result(new Err(e)); | |
} | |
} | |
} | |
export const R = Result.try; | |
// examples | |
const throws = new Promise((_, reject) => reject("blowup")); | |
const one = new Promise((r) => 1); | |
const two = new Promise((r) => 2); | |
const unsafeThing = (await Result.try(throws)).unwrap(); | |
const safe = (await Result.try(one)).and(await Result.try(two)).unwrap(); // 2 | |
const unsafeToSafe = (await Result.try(throws)).or(new Ok(2)).unwrap(); // 2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment