I like the idea of having a finally and a defer.

Jamie



From: 
<[email protected]<mailto:[email protected]>> 
on behalf of Haravikk via swift-evolution 
<[email protected]<mailto:[email protected]>>
Reply-To: Haravikk 
<[email protected]<mailto:[email protected]>>
Date: Monday, June 6, 2016 at 6:44 PM
To: donny wals <[email protected]<mailto:[email protected]>>
Cc: "[email protected]<mailto:[email protected]>" 
<[email protected]<mailto:[email protected]>>
Subject: [EXTERNAL] Re: [swift-evolution] [Proposal] A more liberal placement 
of defer

While I can kind of see where you’re coming from I’m not sure about the change; 
the key thing about defer is that it doesn’t just execute in the cases you 
explicitly define, but can also occur if exceptions are thrown and other exit 
cases that could be all over the scope.

To compare with other languages, I’ve used several that achieve this with a 
finally block instead, usually as part of a try/catch like so:

try { doSomethingThatCanThrow(); return 1; }
catch (Exception e) { print(e); return 0; }
finally { doSomeCleanup(); }

Here you have two possible exit points, and in both cases the code in the 
finally block is executed. But it’s pretty rigid.

This is fine in cases like you suggest where it makes a bit more sense 
visually, but the cool thing about Swift is that you can declare defer blocks 
all over the place, build upon them and so-on. It means you can group your 
cleanup code with the statements that actually require the cleanup, even if 
there is a ton of extra code that comes afterwards. For example, opening a TCP 
connection may use a defer block right away to ensure the connection is closed 
cleanly and any buffers are cleared regardless of how the method ends 
(normally, IO error etc.), but before that happens there may be a whole load of 
parsing and other operations before you hit the final return statement.

It’s also pretty clear from the keyword defer; putting it after the return 
statement actually makes less sense, as there is nothing for it to be deferred 
in relation to (as there’s nothing else left to do).


I’d say that if you want cleanup to appear visually afterwards you’d be better 
off promising a finally block, this could be nice to have, especially if it 
could be applied to most blocks like so:

do {
somethingThatCouldThrow()
if someCondition { return }
} finally { someCleanup() } // Executed whether the block throws, returns or 
completes normally

for eachValue in theValues {
if doSomethingTo(eachValue) { break }
if someCondition { return }
else { throw SomeError() }
} finally { doSomeCleanup() } // Executes regardless of whether the loop ends 
normally, breaks, returns or throws

And so-on. I’d say that defer is more flexible overall, but there could be some 
cause for this visually so you can move simpler deferred code away from the 
main method body.

On 6 Jun 2016, at 20:50, donny wals via swift-evolution 
<[email protected]<mailto:[email protected]>> wrote:

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]<mailto:[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