[swift-evolution] Code blocks and trailing closures

Jaden Geller jaden.geller at gmail.com
Wed Mar 15 07:04:35 CDT 2017


It seems like your complaint is that control-flow statements, specifically `return`, act different inside closures than inside other braced statements. I too dislike this inconsistency, but I don’t think that the syntactic change you suggested makes it much more clear. I’d rather find a solution that’d allow trailing closure functions (like `forEach`) to support keywords like `return`, though I imagine this would require some sort of macro system.

Cheers,
Jaden Geller

> On Mar 15, 2017, at 4:56 AM, Rien via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Sorry, it seems we are talking past each other, let me try again:
> 
> I left the “if” out on purpose. To show that even though the snippet was “valid” code, it was in fact ambiguous.
> 
> With closures (and autoclosures) it becomes possible -to some extent- to “enhance” the language.
> 
> Consider:
> 
> guard let c = somefunc() else { showError(); return }
> myguard( let c = somefunc()) { showError(); return }
> 
> In this simple example it is clear that the second return behaves quite differently from the first.
> It gets more difficult if the code in the block cq closure gets very large.
> Also, I would expect that beginners would have problems understanding this (subtile but important) difference.
> 
> Regards,
> Rien
> 
> Site: http://balancingrock.nl
> Blog: http://swiftrien.blogspot.com
> Github: http://github.com/Balancingrock
> Project: http://swiftfire.nl
> 
> 
> 
> 
> 
>> On 15 Mar 2017, at 12:19, Adrian Zubarev <adrian.zubarev at devandartist.com> wrote:
>> 
>> There is no if … on my screen nor there is one here https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon–20170313/033888.html. May be a typo?
>> 
>> In that case it cannot be a trailing closure because trailing closures are banned in such scenarios. https://github.com/apple/swift-evolution/blob/master/proposals/0056-trailing-closures-in-guard.md
>> 
>> As for the lazy variables you’ve mentioned in the original posts, the closure there is invoked lately but only once and it cannot be reused at all.
>> 
>> Let me know if I understood your gist now.
>> 
>> if someFunction { …; return } // someFunction cannot have a trailing closure here!
>> 
>> 
>> 
>> 
>> -- 
>> Adrian Zubarev
>> Sent with Airmail
>> 
>> Am 15. März 2017 um 12:08:19, Rien (rien at balancingrock.nl) schrieb:
>> 
>>> If I wrote this: 
>>> 
>>> if serverCert.write(to: certificateUrl) { showErrorInKeyWindow(message); return } 
>>> 
>>> then the meaning of return would have been different. 
>>> 
>>> Imo it is a problem that two pieces of code impact the understanding of each other and that those two pieces of code could potentially be very far apart. 
>>> 
>>> I do agree that the parenthesis are not a perfect solution, it was just the first thing that I could think of and that has some level of similarity in meaning. 
>>> 
>>> Regards, 
>>> Rien 
>>> 
>>> Site: http://balancingrock.nl 
>>> Blog: http://swiftrien.blogspot.com 
>>> Github: http://github.com/Balancingrock 
>>> Project: http://swiftfire.nl 
>>> 
>>> 
>>> 
>>> 
>>> 
>>>> On 15 Mar 2017, at 12:00, Adrian Zubarev <adrian.zubarev at devandartist.com> wrote: 
>>>> 
>>>> I’m slightly confused by this. How is a trailing closure different from a code block in Swift? It’s basically the same thing with some extra syntax sugar because it happens to be the last parameter of your function. 
>>>> 
>>>> You can simply write this if you wanted to: 
>>>> 
>>>> myFucntion(someLabel: abc, closureLabel: { …; return }) 
>>>> 
>>>> Parentheses are indicating that your closure is immediately invoked. 
>>>> 
>>>> let someInt = { return 42 }()  
>>>> print(someInt) 
>>>> 
>>>> let someClosureWhichReturnsAnInt = { return 42 } // You can reuse the closure 
>>>> print(someClosureWhichReturnsAnInt()) // Invocation happens now here 
>>>> 
>>>> return is scope based and it’s totally clear (to me) that in your case return will return from your closure with a value of Void. 
>>>> 
>>>> 
>>>> 
>>>> 
>>>> --  
>>>> Adrian Zubarev 
>>>> Sent with Airmail 
>>>> 
>>>> Am 15. März 2017 um 11:35:39, Rien via swift-evolution (swift-evolution at swift.org) schrieb: 
>>>> 
>>>>> What does the following code fragment do? 
>>>>> 
>>>>> serverCert.write(to: certificateUrl) { showErrorInKeyWindow(message); return } 
>>>>> 
>>>>> The only possible answer is: I don’t know. 
>>>>> 
>>>>> The problem is finding out what the “return” statement will do. 
>>>>> 
>>>>> Without knowing if the {...} is a code block or a trailing closure it is impossible to know what the return statement will do. It will either end the closure or it will end the function that contains this code block. 
>>>>> 
>>>>> This could be disambiguated by using the same syntax as for lazy variables: 
>>>>> 
>>>>> serverCert.write(to: serverCertificateUrl) { showErrorInKeyWindow(message: message); return }() 
>>>>> 
>>>>> Now it is clear that the return statement will only terminate the (trailing) closure. 
>>>>> 
>>>>> A question to the educators on the list: Is this a real problem? 
>>>>> 
>>>>> Personally, I dislike this situation, but I am also ambivalent towards the solution I just described. 
>>>>> 
>>>>> Regards, 
>>>>> Rien 
>>>>> 
>>>>> Site: http://balancingrock.nl 
>>>>> Blog: http://swiftrien.blogspot.com 
>>>>> Github: http://github.com/Balancingrock 
>>>>> Project: http://swiftfire.nl 
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> _______________________________________________ 
>>>>> swift-evolution mailing list 
>>>>> swift-evolution at swift.org 
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list