Defer improvement

Hi Swift Evolution Community,

Thanks for the forum in place I have been reading the mailing list since the start but never felt comfortable enough to contribute so please bear with me it's my first pitch.

What if defer can have the return value of a function as a parameter.


// today defer
func toto() -> Int {
	let lock = Lock() defer { lock.unlock }
	return 42
}

// tomorrow defer
func toto() -> Int {
	let lock = Lock() defer { a in
		 lock.unlock 
		 sendToStatBackend(a)
	 }
	 return 42
}


// tomorrow defer with source compat fix
func toto() -> Int {
	let lock = Lock() defer { $0; lock.unlock } // ugly but no source breakage  since it add at compile time
	return 42
}

It can work without breaking the source compatibility if we add $0 in today defer at compile time.

Swift 4.x - Adding a $0; at the beginning of the closure a compile time to dodge the warning "Contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored"

Swift 5.0 - Not adding automatically the $0; to restore the warning "Contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored"

What do you think about it?

1 Like

Defer can be used in scopes other than the top level of a function. For example:

for x in list {
    defer { print(“done processing \(x)”) }
    guard x > 0 else { continue }
    processValue(x)
}

In a case like this, there is no obvious value for the ‘defer’ closure to receive. So there would now have to be two separate variants of ‘defer’. That seems unfortunate.

Further, you can already do something like this in today’s Swift:

func toto() -> Int {
    var returnValue = 42
    lock.lock()
    defer { 
        lock.unlock()
        sendToStatBackend(returnValue)
    }
    if condition { 
        returnValue = 85
    }
    return returnValue
}

It’s not quite the same as your proposal, but if you need that pattern of usage, it is certainly doable today.

1 Like

Thanks @bjhomer for the response.

I didn’t know that defer could be used in other places than top-level functions. This, as you clearly explain render my approach obsolete.