How to defer a call if condition is met?

I’m having a hard time with “defer is executed at the end of the scope” thing.

I want to do conditional defer, i.e. “defer this call if the condition is met”. But I can’t do that with current defer behavior:

foo :: proc() {
    cond := true

    // This won't work, because defered call will be executed at the end of the `if` block 
    if cond {
        defer fmt.println("if cond { defer }")
    }

    // This will won't work because of the same reason
    if cond do defer {
        fmt.println("if cond do defer") 
    }

    // Edit: Same behaviour here
    if cond do defer fmt.println("if cond do defer") 

    // This won't work because `if cond` check will be executed at the end of the procedure
    // and at that moment cond will be modified to false
    defer if cond {
        fmt.println("defer if cond")
    }

    cond = false
    fmt.println("exit")
}

Is there a way to evaluate if outside of defer and at the same time defer the call on the procedure level (and not in if block level)?

I am completely new and clueless to Odin, but why not:

if cond do defer fmt.println("if cond do defer")

Untested, but it just might work :smile:

Edit: I read/saw somewhere that “braces or a do are always required”

Tested it now, it worked the same way as if cond do defer { … }

foo :: proc() {
    cond := true

    // This won't work, because defered call will be evalueted at the end of the if block 
    if cond {
        defer fmt.println("if cond { defer }")
    }

    // This will won't work because of the same reason
    if cond do defer {
        fmt.println("if cond do defer {}") 
    }

    // Same behaviour here
    if cond do defer fmt.println("if cond do defer") 

    // This won't work because if cond check will be evaluated at the end of the procedure
    // and at that momend cond will be modified to false
    defer if cond {
        fmt.println("defer if cond")
    }

    cond = false
    fmt.println("exit")
}
if cond { defer }
if cond do defer {}
if cond do defer
exit

I tested it by copying the cond to other_cond and set other_cond to false:

...
    other_cond: bool = cond
    other_cond = false
    fmt.println("exit")
}

The output:

if cond { defer }
if cond do defer {}
if cond do defer
exit
defer if cond

If it doesn’t work with the same boolean, why not capture it at the start of the procedure and use that for the defer?
I did it the other way around out of laziness :slight_smile:

Edit: I know that I am not really answering your question, but it’s better than no input, I hope!

Technically yes, it would be better to not reuse original boolean. But I can think of situations when that’s not the case. E.g. when using ok variable with multiple function calls

If any function call fails, and you are forced to exit/panic, then the defers will be called at the end of scope, so no need to use a bool to test if a defer should be set.
I wouldn’t use defer for program logic, just something that is guaranteed to be called if something goes awry. Like _at_exit() or whatsitcalled in C.

See → Idioms - “defer if” - Odin Docs