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

Reply via email to