[swift-evolution] named parameters - why hidden first?/proposal interest

Dave Abrahams dabrahams at apple.com
Thu Jan 21 14:05:56 CST 2016


on Thu Jan 21 2016, David Owens II via swift-evolution <swift-evolution-m3FHrko0VLzYtjvyW6yDsg-AT-public.gmane.org> wrote:

> Ok, this is something that's bugged me since Swift was released. It
> was almost fixed it back in the 1.x days (I think that was when it
> changed to be a bit more consistent between top-level funcs and
> members funcs).
>
> The question is this, why do we still implicitly have unnamed first
> parameters for non-init functions, and in some cases, suggest putting
> the name of the first parameter in the name of the function?
>
>     func say(message: String, times: Int) { ... } // or
>     func sayMessage(message: String, times: Int) { ... }
>
>     say("hello world", times: 5) // or
>     sayMessage("hello world", times: 5)
>
>     // vs.
>
>     say(message: "hello world", times: 5)

Hi David; thanks for asking.  This is very much related to the upcoming
API Design Guidelines review
(https://github.com/apple/swift-evolution/blob/master/proposals/0023-api-guidelines.md),
so we may have an opportunity to discuss it in more depth.  For now, I'm
going to give you my personal opinion below.

> Let me be clear, I completely understand why the _ is supported, and I
> understand that it's not feasible to implicitly convert all the ObjC
> interfaces to move the parameter name into the first position (though
> they could be annotated to do this...).
>
> However, why are we continuing that tradition with _new_ Swift APIs?
> There seems to be a perfectly good spot for the first parameter name
> of a function: the first parameter slot.

First of all, I've found the convention to work quite well for the
standard library.  IMO well-designed APIs typically don't have many
parameters, and methods that take a single parameter are in fact
extremely common.  In these cases, the parameter often functions
grammatically as the direct object of the statement being made in the
call, adding a label doesn't help readability.  It's

    x.remove(y)

vs

    x.remove(containedThing: y)

or 

    x.removeContainedThing(y)

It's my strong belief that it's usually impossible to improve on
"x.remove(y)".  The less-common case where x contains a bunch of
different kinds of things and removing each kind is semantically
different—e.g. UIViews contain subviews and gestureRecognizers—is a
notable exception.

Of the methods and functions with multiple parameters, many of them have
one primary parameter that functions as a direct object, and a few other
parameters—often with defaults—used to "tune" the overall behavior of
the method.  So in these cases, having no label is appropriate as well
(c.f. print).

> The seemingly poor choice of this shows up in other places too, like
> Doug Gregor's Naming Functions with Arguments Labels proposal. The
> default for that is to always have the _ in the first name slot.
>
>     say(_:times:)
>     sayMessage(_:times:)
>
>     // vs.
>
>     say(message:times:)

I don't see why that's a problem; it's a side effect of most methods not
having an initial label, while some do.  

> The other unfortunate thing about this, is that this is another
> instance where "init" behaves differently then the rest of Swift. I
> think it would be great to unify this.
>
> Am I just missing the really compelling rationale for this?

Aside from single-argument, type-conversion initializers (on which by
convention we are dropping the initial label), initializeations tend to
be different from methods and function calls.  There's no way for the
first argument to function as a direct object of a phrase, so they are
more functional/declarative than method calls.

I do have a few disagreements with the API guidelines in this area, but
I'm going to leave that discussion for the review.


Hope this helps,
Dave



More information about the swift-evolution mailing list