5 ms·
Well I think the function scope the most useful, but wish there was block scope available too. So what I really wish was that languages used dot notation to go
by willvarfar 9y ago
Well I think the function scope the most useful, but wish there was block scope available too.
So what I really wish was that languages used dot notation to go up scope eg ..name is that name two blocks out. This was one of the good parts of VB syntax which I miss in other languages. Think how much nicer it is than python's nonlocal and global, for example!
- br1 9y agoIt's true that defer is more powerful at function scope. You can always recover block scope with an unnamed func. But it doesn't fit with normal lexically scoped constructs. You get gotchas. I would love to be able to explicitly affect other scopes as you mention, for example to define two classes at the same time.
- pcwalton 9y agoWhat's the use case for function scoped defer? I have never once needed function scoped RAII in C++ or any other language.
- br1 9y agoCollecting tasks from all iterations to await before returning.
- barsonme 9y agoIt's not terribly uncommon for larger functions to do something like func someSQLStuff() { tx, err := createTx() defer func() { if err != nil { tx.Rollback() log(err) } else { tx.Commit() } }() rows, err = tx.QueryContext( ... ) // more SQL } Basically, function-scoped cleanup. Like closing opened files.
- Groxx 9y agoI have a comment at a higher level with a broader example, but for Go at least this is somewhat common: func f(i interface{}) { if closable, ok := i.(closable); ok { defer closable.close() } // do stuff with i, maybe other casts, etc } There aren't many nice options for "if I can call X, defer a call to X" aside from shoving it into an `if`, where it'd be captured by that scope. I mean, you could do something like deferrable := func(){} if closable { deferrable = closable.close } defer deferrable() but imagine doing that every time. It'd work, sure, but it'd also be more annoying.
- pcwalton 9y agoCouldn't you do: func closeIfNecessary(object interface{}) { closable, needsClosing := object.(closable) if needsClosing { closable.close() } } And then just do: func f(i interface{}) { defer closeIfNecessary(i) ... } Doing it this way also saves you boilerplate by factoring the downcast out into a separate function.
- Groxx 9y agoAs long as you can always call .close() regardless of the code below, yep - that'd work, and is definitely more readable. If you can't call it unless [some other conditions], it goes back to the same kind of problem though. "closable" may not be a good choice on my part, as they're often called unconditionally.