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 <[email protected]> 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
>> <[email protected]>:
>>
>> 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
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution