-
-
Save superamadeus/e81c0524d6991c6977cb4ab34b82321a to your computer and use it in GitHub Desktop.
Informal "try expression" proposal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Proposal: Try expression. | |
* Goal: Facilitate imperative exception handling | |
*/ | |
// Current exception handling pattern | |
try { | |
const user = await userRepo.getUserById(1); | |
console.log(`Hello, ${user.name}!`); | |
} catch (e) { | |
console.warn(e.message); | |
} | |
// Desired exception handling pattern | |
const [user, getUserFailed] = try await userRepo.getUserById(1); | |
if (!getUserFailed) { | |
console.log(`Hello, ${user.name}!`) | |
} else { | |
console.warn(getUserFailed.exception.message); | |
} | |
// Edit: examples not using await: | |
const books = [ | |
{ author: "Brandon", title: "Magic Numbers"}, | |
{ author: "Anthony", title: "Stupid Numbers"}, | |
] | |
function getBookAuthorOrThrow(id) { | |
const book = books[id]; | |
if (book == null) { | |
throw new Error(`Could not find book with this id (${id})`); | |
} | |
return book.author; | |
} | |
function sayHelloToBookAuthor(bookId) { | |
const [bookAuthor, getBookAuthorFailed] = getBookAuthorOrThrow(bookId); | |
if (!getBookAuthorFailed) { | |
console.log(`Hello, ${bookAuthor}!`); | |
} else { | |
console.log(console.log(getBookAuthorFailed.exception.message)) | |
} | |
} | |
sayHelloToBookAuthor(1); // output: Hello, Brandon! | |
sayHelloToBookAuthor(100); // output: Could not find book with id (100). | |
// Simpler example: | |
const result1 = try 100; | |
const result2 = try (() => { throw new Error() })(); | |
console.log(result1); // [100, undefined]; | |
console.log(result2); // [undefined, TryFailure { exception: Error }]; | |
// Approximate implementation with current features | |
class TryFailure { | |
constructor(exception) { | |
this.exception = exception; | |
} | |
} | |
function _try(fn) { | |
try { | |
const result = fn(); | |
if (_isPromise(result)) { | |
return _tryAsync(result); | |
} | |
return _trySuccess(result); | |
} catch (e) { | |
return _tryFailure(e); | |
} | |
} | |
async function _tryAsync(promise) { | |
try { | |
return _trySuccess(await promise); | |
} catch (e) { | |
return _tryFailure(e); | |
} | |
} | |
function _isPromise(o) { | |
return o != null && typeof o.then === "function"; | |
} | |
function _trySuccess(result) { | |
return [result, undefined] | |
} | |
function _tryFailure(exception) { | |
return [undefined, new TryFailure(exception)] | |
} | |
const [user, getUserFailed] = await _try(() => userRepo.getUserById(1)); | |
// Edit: examples not using await: | |
function getBookOrThrow(id) { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment