[swift-evolution] [Proposal] A more liberal placement of defer

michael.peternell at gmx.at michael.peternell at gmx.at
Mon Jun 6 15:25:29 CDT 2016


Hi,

I think that's an awful idea. I can already tell you that this will never be accepted. It just complicates the design and the semantics of the `defer` statement, and I don't see any advantage. Sorry.

-Michael

> Am 06.06.2016 um 22:14 schrieb donny wals via swift-evolution <swift-evolution at swift.org>:
> 
> Michael,
> 
> How would this proposal break your snippet?
> 
>> func g(x: Int) {
>>   defer { print("A"); }
>>   let b: Int
>>   if x == 3 {
>>       return
>>   } else {
>>       b = x
>>   }
>>   defer { print("b is \(b)") }
>> }
> 
> In this case if x==3 the function should return without executing the final defer. The reason I think it should work like that is that the if statement creates a scope of it’s own. You’re using a return inside of that scope, so only if you’re adding a defer inside of that scope it should be executed even if it’s after the return. The important part here is that the return and the defer should be in the same scope for this proposal to apply.
> 
>> On 06 Jun 2016, at 22:07, Michael Peternell <michael.peternell at gmx.at> wrote:
>> 
>> Hi,
>> 
>> you may think of `defer` as a function that pushes a block onto an implicit cleanup stack that is part of every lexical closure. On each scope exit, all blocks from its cleanup stack are popped and executed.
>> 
>> E.g.:
>> 
>> func f(x: Int) {
>>   defer { print("A"); }
>>   defer { print("B"); }
>>   if x == 3 {
>>       return
>>   }
>>   defer { print("C"); }
>> }
>> 
>> So, f(2) will print "CBA", but f(3) will print "BA" instead. Furthermore, this will change semantics and break the following code:
>> 
>> func g(x: Int) {
>>   defer { print("A"); }
>>   let b: Int
>>   if x == 3 {
>>       return
>>   } else {
>>       b = x
>>   }
>>   defer { print("b is \(b)") }
>> }
>> 
>> In the code above, b is only defined if x is not 3. If x is 3, the last `defer` block cannot be called, and that code would no longer compile.
>> 
>> So I think the current language behavior is more powerful. `defer` is usually used to do cleanup work, and it is called near the place where some resource is initialized. Putting a `defer` block to the end of a function kinda defeats its purpose. And simple functions like fibonacci I would just write without using `defer` at all - it's just confusing to use `defer` and `inout` in this case IMO.
>> 
>> /// Calculates the n'th fibonacci number. (n >= 1)
>> func fibonacci(n: Int) -> Int {
>>   var a = 0
>>   var b = 1
>>   for _ in 1...n {
>>       (a,b)=(b, a+b)
>>   }
>>   return a
>> }
>> 
>> Regards,
>> Michael
>> 
>> 
>>> Am 06.06.2016 um 21:50 schrieb donny wals via swift-evolution <swift-evolution at swift.org>:
>>> 
>>> Hi,
>>> 
>>> When we’re using defer we write some code that we want to execute the moment a scope exits.
>>> This leads to code that could read like:
>>> 
>>> let fibonacci = sequence(state: (0, 1)) { (pair: inout (Int, Int)) -> Int in
>>>  defer { pair = (pair.1, pair.0 + pair.1) }
>>>  return pair.0
>>> }
>>> 
>>> What I find strange about this is that we have to write the code that we want to execute after the return before the return.
>>> 
>>> I’d like to propose a change to defer that would allow the above code to be written as:
>>> 
>>> let fibonacci = sequence(state: (0, 1)) { (pair: inout (Int, Int)) -> Int in
>>>  return pair.0
>>>  defer { pair = (pair.1, pair.0 + pair.1) }
>>> }
>>> 
>>> This would make the intent of the code more clear (return first, then mutate state). Not all cases can benefit from this change, but anytime you exit a scope using a return I think it might be more clear to define the defer after the return. The code would more closely mirror the intent of the code.
>>> 
>>> A rule of thumb I’ve come up with for this is that whenever you’re using return to exit a scope, any defer in that same scope should be executed regardless of it’s position in that same scope. This proposal would supplement the way defer currently works.
>>> 
>>> What do you all think?
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list