Yeah, it’s a common idiom for sure, and if you use a temporary variable that is still potentially accessable after its deinitialization I would definitely use it.
I would suggest something like this:
const ConnectAttempt = union {
ok: Connection,
fail: ConnectFail,
pub fn init(params: ConnectParams) ConnectAttempt { ... }
pub fn deinit(attempt: *ConnectAttempt) void {
switch (attempt) {
.ok => |*conn| => conn.deinit(),
.fail => |*fail| => fail.deinit(),
}
}
};
pub fn main() !void {
const params = mylib.ConnectParams{ .string = "dbname=jbe" };
var attempt = mylib.ConnectAttempt.init(params);
defer attempt.deinit();
switch (attempt) {
.ok => |*conn| {
// use conn here
},
.fail => |*fail| {
std.debug.print("{s}\n", .{fail.message()});
},
}
}
This way initialization and deinitialization happen in the same scope right next to each other which helps avoid bugs and confusion IMO especially if you plan to add a lot of code to the switch prongs or more cases in the future.