Le 2 janv. 2016 à 9:25, Maury Markowitz via swift-evolution 
<swift-evolution@swift.org> a écrit :

> I'm confused about 'defer'. Not the purpose, the chosen syntax. 
> 
> func confusing() {
>    print("1")
>    defer { print("2") }
>    print("3")
> }
> 
> Produces 1,3,2. Trying to describe what is happening here is non-trivial... 
> it runs line 1, then we put line 2 on a stack, then line three runs, then we 
> pop the stack... what?! And stepping through it in the debugger... ugh.
> 
> Unless I missed something obvious, wouldn't placing "code that always has to 
> run at the end" actually *at the end* not make more sense? Like this...
> 
> func clear() {
>    print("1")
>    print("3")
> 
>    always { print("2") }
> }
> 
> Not only is the code clearly expressing its intent, the actual execution is 
> following the source.

With your proposal, code like this:

func test() throws -> T {
        let a = try makeSomething()
        defer { a.cleanup() }

        let b = try makeSomething()
        defer { b.cleanup() }

        return try compute(a, b)
}

would have to be rewritten somewhat like this:

func test() throws -> T {
        let a = try makeSomething()
        do {
                let b = try makeSomething()
                do {
                        return try compute(a, b)
                        always { b.cleanup() }
                }
                always { a.cleanup() }
        }
}

which is a bit inconvenient. One important thing with `defer` is that where you 
put it in the function impacts at which point it gets pushed on the "cleanup 
stack", something that gets lost with `always` and which I need to add back 
through `do {}` blocks here.

I think what you are looking for is a `do {} finally {}` block, which you 
should feel free to propose if you think it's worth it. I personally don't 
think it makes the above example better, but it certainly has the benefit of 
always running things in source order.

func test() throws -> T {
        let a = try makeSomething()
        do {
                let b = try makeSomething()
                do {
                        return try compute(a, b)
                } finally {
                        b.cleanup()
                }
        } finally {
                a.cleanup()
        }
}

-- 
Michel Fortin
https://michelf.ca

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to