-
Notifications
You must be signed in to change notification settings - Fork 0
Description
A Zig tracking issue for blockers and wishes, as per this wiki page.
There are no hard blockers for Havarti porting to Zig from Go at this point. They will be added here if/when they show up.
Here are some wishes below.
1. Something like an okdefer keyword
Currently the only frustrating imbalance is the lack of something like an okdefer keyword. For database transactions in particular this would be useful. For example:
// All setup and teardown is clustered in one place and intent is clear:
// * on error rollback the transaction
// * on success commit the transaction
var tx = try db.Transaction.begin();
errdefer tx.rollback();
okdefer tx.commit();
// Do all work the afterwardAlternatives
Do nothing and hope people remember to Do the Right Thing ™️ when dealing with early returns
Example:
pub fn doWork(db: DatabaseType) !void {
var tx = try db.Transaction.begin();
errdefer ts.rollback();
// do some work
// Check for early return
if(earlyReturnCondition()) {
// Don't forget to commit!
tx.commit()
return;
}
// do some more work
if(otherEarlyReturnCondition()) {
// Don't forget to commit!
tx.commit()
return;
}
// do yet more work
tx.commit();
}Reasons against
This is hoping the developer isn't forgetful. It seems to be antithetical to Zig's philosophy of making it easy to do the right thing in this circumstance.
Using another function
Example:
fn innerWork(db: DatabaseType) !void {
// do work here
}
pub fn outerWork(db: DatabaseType) !void {
var tx = try db.Transaction.begin();
errdefer tx.rollback();
try innerWork(db);
tx.commit();
}Reasons against
This is clunky and doesn't make intent as clear. Another dev may add more code in the outerWork function without realizing that all work should be in the innerWork function. Code comments would help, but having an okdefer keyword makes intent unmistakably clear. This is clearly better than just hoping people remember to Do The Right Thing, but it still isn't ideal.
Use regular defer and a tracking variable
Example:
var tx = try db.Transaction.begin();
var txok = true;
defer if (txok) tx.commit();
errdefer tx.rollback();
errdefer txok = false;
// Do all work the afterwardReasons against
Syntax it clunky, pollutes the namespace with extra variables, and makes the setup/teardown order dependent. Whereas errdefer and okdefer can be specified in any order and work just fine, this approach requires errdefer statements be defined last so that they are executed before the defer statements used for successful exit (since defered expressions execute in reverse order). This at least bundles all setup/teardown together. But it could easily break things without care.
Background
There was a prior proposal similar to this, but it seemed to be closed without being implemented. My guess is that it was mostly because the proposal didn't give a strong use case. However, Havarti uses database transactions all over the place. Being able to use this as a pattern would make code vastly cleaner and clearer; I think there is a strong use case with DB transaction rollback versus commit.