[swift-evolution] Better syntax for deferred?

Michel Fortin michel.fortin at michelf.ca
Sat Jan 2 12:40:24 CST 2016


Le 2 janv. 2016 à 9:25, Maury Markowitz via swift-evolution <swift-evolution at 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



More information about the swift-evolution mailing list