6

Here's an example of what I'm talking about: https://developer.apple.com/documentation/foundation/nsmutableorderedset/1410287-insert

The insert function is shown as insert(_:at:)

When it's actually used, the insert function looks more like:

namesArray.insert("John", at: 3)

There's no : after "John" (though I suppose it could be "John":String -- is that what it's there for?), and the , that actually needs to go there is not mentioned in the function signature in the documentation. Am I just supposed to know/assume that the comma goes there when I actually use it? Is this the case for all Swift functions?

Please note that this is not a question about the underscore, _ -- I understand why it's there and what it's for. I'm specifically asking about the reasons for including : and not including , in the function signature.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Matvey
  • 335
  • 4
  • 18
  • It’s just a notation! This is the convention the language designers picked. Asking why is like asking why a touchdown is 6 points. Those are the rules of the game, that’s why. – matt Feb 05 '19 at 15:23
  • 2
    There is _nothing to explain_. Why do we use `()` and not `<>` to surround function parameters? Why do we use `""` and not `^^` to surround a string literal? Because those are the rules of the language. – matt Feb 05 '19 at 15:32

4 Answers4

27

The convention, frequently seen in documentation, is a concise way of referring to a function, using only the function name and argument labels.

So consider this function declaration:

func insert(_ objects: [Any], at indexes: IndexSet)

This is

  • a method called insert;
  • the first parameter name is called objects, this parameter has no argument label (designated with the _) and has a type of [Any]; and
  • the second parameter name is indexes, its argument label is at and has a type of IndexSet.

So you call it like so:

insert(someObjects, at: someIndex)

When you call it, you don’t care what the parameter names that are used inside that function, but rather just what the argument labels are. So, the convention when referring to that method in documentation is to omit the parameter names and types and just use the function name and the argument labels, but no comma:

insert(_:at:)

Note, you’d never actually use this syntax in your code. This is just a documentation convention employed to distill long function declarations down to something more manageable and concise:

transition

For more information about argument labels and parameter names, see Function Argument Labels and Parameter Names

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • thank you Rob, this explains it! P.S. how did you create that beautiful gif at the bottom? – Matvey Feb 05 '19 at 21:37
  • 7
    I cheated: KeyNote presentation with magic move, capture with QuickTime and then converted to gif. I just wanted to illustrate what was going on visually. – Rob Feb 05 '19 at 22:11
3

A : in the function signature always means an input argument to the function. The function signature contains the argument label followed by a :. The _ means there's no argument label, in which case you can omit the : as well when supplying that specific input argument to the function call.

This is exactly what you see with the insert(_:at:) function. You supply two input arguments to it, "John" and 3, but it only needs an argument label for the second input argument, hence you only need one :. It's also important to note that at call time, you separate the input arguments using ,, not :.

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
2

Swift functions have a unique way of specifying the signature, which is a carry over pattern from Objective C. There are 3 parts to specifying each input argument to the function signature. The signature for the function you mentioned is as follows:

func insert(_ objects: [Any], 
     at indexes: IndexSet)

Let's look at the second argument first:

  1. at indicates the argument label, which is how the caller specifies the parameter.
  2. indexes indicates the function's parameter name to the object. This means that in the body of the function, whatever was passed as at: would be referred to as indexes.
  3. IndexSet is the type of the argument.

Part 1 can be something besides a name, too:

  • if it is not specified, the argument name and parameter label are the same. For example, if the signature were func insert(objects: [Any], indexes: IndexSet), the function would be called as o.insert(objects: ['a','b'], at: [1,2]).
  • If it is an underscore (_), then the argument has no label for the caller. This allows the caller to use the simpler, intuitive call o.insert(['a','b'], at: [1,2]).
Bob Zimmermann
  • 938
  • 7
  • 11
  • 1
    What you call `binding` is called `argument name` and there's no `function label`, but `argument label`s. – Dávid Pásztor Feb 05 '19 at 15:41
  • 2
    @DávidPásztor - Technically, while those labels you supply when you call the function are called arguments (i.e., "argument label”), what you reference inside the function is a parameter (hence “parameter name”). See See [Function Argument Labels and Parameter Names](https://docs.swift.org/swift-book/LanguageGuide/Functions.html#ID166). – Rob Feb 05 '19 at 17:23
1

In a signature, the colon separates the name of a parameter from its value. Functions have this anatomy:

func functionName(label1 parameter1: Type1, label2 paramter2: Type2) -> ReturnType {
    ...
}

where labels are the names seen when calling the function and parameters are the names of the values as used in the body of the function. A label of _ removes the label from the parameter when calling it.

When calling a function, the colon simply separates parameter labels from the values passed to the function. Commas separate different parameters. A parameter with no label requires no colon. The following function would have no colons at all:

func myFunc(_ par1: Int, _ par2: String) {
    print(par1, par2)
}

myFunc(3, "what") // 3 "what"
kid_x
  • 1,415
  • 1
  • 11
  • 31