[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