[swift-evolution] [Thoughts?][Phase2] default arguments and trailing closure syntax

Haravikk swift-evolution at haravikk.me
Sat Jan 7 06:51:24 CST 2017

> On 5 Jan 2017, at 02:25, Jay Abbott via swift-evolution <swift-evolution at swift.org> wrote:
> When you have a function with a closure and then another optional default = nil closure at the end, like this:
> open static func animate(identifier: String,
>                          duration: Double,
>                          update: @escaping AnimationUpdate,
>                          completion: AnimationCompletion? = nil) {
> You can’t use trailing closure syntax for the update argument when leaving the completion argument out/default.
> This kind of breaks one of the benefits of default arguments, which is that you can add them to existing released functions without breaking the calling code. This means you have to add a separate convenience function without the extra argument, which is annoying and inelegant. Another annoying thing is that you can easily miss this error if you happen to not use trailing closure syntax in your tests or other usage, because adding the extra default argument compiles fine for code that uses normal syntax.
> Are there any issues/gotchas if the trailing closure syntax were to work for the last specified argument rather than the last defined argument?

I'm not sure I'd call having another convenience function "annoying and inelegant" personally, as that's kind of the whole point of them, but yes I do agree in this case it could be handled more easily.

Personally I like the idea of having a new @trailing attribute to allow any closure to be specified as the trailing closure, regardless of placement, as this would also be useful for methods where you may accept multiple closures, but where it may make the most logical sense to have say a main body closure as the first parameter, yet it also makes most sense to be the trailing closure, which becomes awkward.

I'm not in favour at all of allowing multiple trailing closures as someone mentioned, I think one is enough (and even then, I only really like them personally for language-construct like methods such as .forEach and similar).

However, I think the real issue in this specific example is that the function/method is being modified after its initial definition, and I wonder if this falls into the ability to reorder arguments? Since most Swift methods and functions have argument labels it doesn't necessarily matter if they are given in a different order as they are still well-defined; thing is, I think Swift actually had this ability and no-one was using it so I don't know if reintroducing it would be the right fix, unless perhaps it is done as an attribute of the function/method?

For example:

static func animate(identifier: String, duration: String, update: @escaping AnimationUpdate, completion: AnimationCompletion? = nil) { … }

With this attribute the order of the parameters is no-longer fixed, but as update is still the last closure it is considered to be the trailing closure? A @trailing attribute would still be useful in this case though as it's possible the new parameter(s) might include a new closure, and you wouldn't want it to suddenly become the new trailing closure.

Also, can't test right now, but can you not add your new completion parameter before the update closure? This should still satisfy existing calls to the method while allowing others to optionally set the completion parameter?

Finally, one other interesting thought, but could we simply allow trailing closures to be any closure the developer hasn't defined? For example:

	function myFunc(body:() -> Void, loop: () -> Bool) { … }
	myFunc(loop: myLoopClosure) { /* this is the body */ }
	myFunc(body: myBodyClosure) { /* this is the loop closure */ }

Perhaps that's a bit too confusing and should be activated with an attribute, but it should be possible to allow this as in both calls above the closure that is trailing is unambiguous.

Just my thoughts on all possible solutions I can think of ;)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170107/484d4082/attachment.html>

More information about the swift-evolution mailing list