> On 5 Jan 2017, at 02:25, Jay Abbott via swift-evolution
> <[email protected]> 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:
@reorderable
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 ;)_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution