Hacker News new | ask | show | jobs
by infogulch 3100 days ago
I think function scope is a good default, and wrapping in an anonymous function and calling it (like your last example) is a simple workaround to get the scope_defer behavior. If it was scope based there's nothing you could do to get func_defer behavior.
2 comments

Yeah, I generally feel the same way. For fairly simple use, scope is more consistent (all scopes / closures are identical), but func is a bit more flexible if you're willing to pay with simple boilerplate.

I mean, you can convert them into each other. Scoped can do something like this (go+python blended code 'cuz lazy):

    func f(){
      deferred := []
      defer func() { for d in deferred.reverse(): d() }() // plus error handling
      if x.something() {
        deferred.push(func(){ cleanup() });
      }
      // same as func scope
    }
but that's a bit more ridiculous / error-prone (though a helper func is obviously possible) than the equivalent IIFE for func -> scope. More explicit, I suppose, but bleh.
It's more explicit, which is a good thing, as it makes the intent clear. This matters if, for example, the function is later refactored to inline into a caller.
It also allows more flexibility (do you execute them in the order they were enqueued, or in reverse?), more room for errors, confusion between different patterns / lack of consistency across different codebases, etc.

Explicit-all-the-things isn't an unambiguous Good Thing™. If it were, we wouldn't even be discussing this - it's an abstraction, which is less explicit than e.g. building defer out of a list and using GOTO.

> If it was scope based there's nothing you could do to get func_defer behavior.

That's clearly false. You could set up a list to hold objects to be disposed (or, more generally, closures to execute) and defer a simple procedure that disposes of all objects in the list. This is in fact what the implementation of defer must do internally.

I think by that he means it wouldn't be possible to get func_defer behavior in the example with a single keyword, or without some form of qualifier. The compiler wouldn't be able to differentiate the behavior.