- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 2.2k
 
all: implement scoped defer (part 1) #25639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| 
           imho it should be the default, without needing a flag  | 
    
          
 That's exactly the idea. But vlib has code that uses   | 
    
| 
           I am adding this example, since there was confusion on Discord about the order of execution with the scoped defers: for i in 1 .. 4 {
	defer { println('Deferred execution for ${i}. Defer 1.') }
	defer { println('Deferred execution for ${i}. Defer 2.') }
	defer { println('Deferred execution for ${i}. Defer 3.') }
	println('Hello, World! ${i}')
}produces: i.e. with   | 
    
| 
           Why is there a special syntax for  I would prefer to use the same syntax for both cases, so that no changes to existing code would be required. I think there is no need to clarify that the  fn foo() {
    defer {
        println('Deferred execution for fn scope (old behavior)')
    }
 
    for i in 1 .. 4 {
        defer {
            println('Deferred execution for ${i}')
        }
        println('Hello, World! ${i}')
    }
    println('Hello, World!')
} | 
    
| 
           @gechandesu Since  $ cat x.v
fn main() {
        {
                defer { println('defer inside main().scope.1') }
                println('hi from main().scope.1')
        }
        println('hi from main().scope.0')
}
$ ./v -scoped-defer run x.v
hi from main().scope.1
defer inside main().scope.1
hi from main().scope.0With  $ cat x.v
fn main() {
        {
                defer(fn) { println('defer inside main().scope.1') }
                println('hi from main().scope.1')
        }
        println('hi from main().scope.0')
}
$ ./v -scoped-defer run x.v
hi from main().scope.1
hi from main().scope.0
defer inside main().scope.1 | 
    
| 
           I consider this first part of the scoped-defer implementation complete. V can also parse, generate, and format the  To do: 
  | 
    
| 
           Excellent work @StunxFS . Thank you very much for working consistently on this important feature 🙇🏻♂️. I worked on another implementation of it last year in https://github.com/spytheman/v/tree/scoped_defer, but I could not progress it as much as you did here.  | 
    
| 
           @gechandesu you are right, that  (edit: my expectation is that at least for the V repo, in say 90% of the cases, they will work regardless, since they modify things for which the order does not matter, as long as they are executed once the function finish, but I may be wrong ... the biggest difference between the two is for defers in loops, and it was not used like that before)  | 
    
| 
           @medvednikov I think that this PR is an excellent improvement.  | 
    
| 
           Great job @StunxFS I agree with the new default behavior. I'd use   | 
    
Based on #22445 (comment).
This PR modifies the behavior of
deferso that it only executes at the end of the scope where it was declared. Currently,deferonly executes at the end of each function.To test this new behavior, you can pass the
-scoped-deferflag to the compiler.For example, this piece of code:
If we compile it with the V compiler using the current behavior, we have:
But with this PR we have:
The old behavior can still be obtained by using
defer(fn) {.Fix #14701.
Fix #22445.
Fix #24663.