File: StdlibAPIGuidelines.rst

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (247 lines) | stat: -rw-r--r-- 7,448 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
:orphan:

.. default-role:: code

=======================================
Swift Standard Library API Design Guide
=======================================

.. Note:: This guide documents *current practice* in the Swift
          standard library as of April 2015.  API conventions are
          expected to evolve in the near future to better harmonize
          with Cocoa.

The current Swift Standard Library API conventions start with the
Cocoa guidelines as discussed on these two wiki pages: [`API
Guidelines <http://cocoa.apple.com/cgi-bin/wiki.pl?API_Guidelines>`_,
`Properties <http://cocoa.apple.com/cgi-bin/wiki.pl?Properties>`_],
and in this `WWDC Presentation
<http://cocoa.apple.com/CocoaAPIDesign.pdf>`_.  Below, we list where
and how the standard library's API conventions differ from those of
Cocoa

Differences
===========

Points in this section clash in one way or other with the Cocoa
guidelines.

The First Parameter
-------------------

* The first parameter to a function, method, or initializer typically
  does not have an argument label:

  .. parsed-literal::

    alligators.insert(fred)           // yes
    if alligators.contains(george) {  // yes
      return
    }

    alligators.insert(**element:** fred)           // no
    if alligators.contains(**element:** george) {  // no
      return
    }

* Typically, no suffix is added to a function or method's base name in
  order to serve the same purpose as a label:

  .. parsed-literal::

    alligators.insert\ **Element**\ (fred)           // no
    if alligators.contains\ **Element**\ (george) {  // no
      return
    }


* A preposition is added to the end of a function name if the role of
  the first parameter would otherwise be unclear:

  .. parsed-literal::

    // origin of measurement is aPosition
    aPosition.distance\ **To**\ (otherPosition)

    // we're not "indexing x"
    if let position = aSet.index\ **Of**\ (x) { ... }

* Argument labels are used on first parameters to denote special
  cases:

  .. parsed-literal::

    // Normal case: result has same value as argument (traps on overflow)
    Int(aUInt)

    // Special: interprets the sign bit as a high bit, changes value
    Int(**bitPattern**: aUInt)

    // Special: keeps only the bits that fit, losing information
    Int32(**truncatingBitPattern**: anInt64)

Subsequent Parameters
---------------------

* Argument labels are chosen to clarify the *role* of an argument,
  rather than its type:

  .. parsed-literal::

    x.replaceSubrange(r, **with:** someElements)

    p.initializeFrom(q, **count:** n)

* Second and later parameters are always labeled except in cases where
  there's no useful distinction of roles::

    swap(&a, &b)                                                    // OK

    let topOfPicture = min(topOfSquare, topOfTriangle, topOfCircle) // OK

Other Differences
-----------------

* We don't use namespace prefixes such as "`NS`", relying instead on
  the language's own facilities.

* Names of types, protocols and enum cases are `UpperCamelCase`.
  Everything else is `lowerCamelCase`. When an initialism appears, it
  is **uniformly upper- or lower-cased to fit the pattern**:

  .. parsed-literal::

     let v: String.\ **UTF**\ 16View = s.\ **utf**\ 16

* Protocol names end in `Type`, `able`, or `ible`.  Other type names
  do not.

Additional Conventions
======================

Points in this section place additional constraints on the standard
library, but are compatible with the Cocoa guidelines.

* We document the complexity of operations using big-O notation.

* In API design, when deciding between a nullary function and a property for a
  specific operation, arguments based on performance characteristics and
  complexity of operations are not considered.  Reading and writing properties
  can have any complexity.

* We prefer methods and properties to free functions.  Free functions
  are used when there's no obvious `self` ::

    min(x, y, z)

  when the function is an unconstrained generic ::

    print(x)

  and when function syntax is part of the domain notation ::

    -sin(x)

* Type conversions use initialization syntax whenever possible, with
  the source of the conversion being the first argument::

    let s0 = String(anInt)            // yes
    let s1 = String(anInt, radix: 2)  // yes
    let s1 = anInt.toString()         // no

  The exception is when the type conversion is part of a protocol::

    protocol IntConvertible {
      func toInt() -> Int // OK
    }

* Even unlabeled parameter names should be meaningful as they'll be
  referred to in comments and visible in "generated headers"
  (cmd-click in Xcode):

  .. parsed-literal::

    /// Reserve enough space to store \`\ **minimumCapacity**\ \` elements.
    ///
    /// PostCondition: \`\ capacity >= **minimumCapacity**\ \` and the array has
    /// mutable contiguous storage.
    ///
    /// Complexity: O(\`count\`)
    mutating func reserveCapacity(_ **minimumCapacity**: Int)

* Type parameter names of generic types describe the role of the
  parameter, e.g.

  .. parsed-literal::

     struct Dictionary<**Key**, **Value**> { // *not* Dictionary<**K**, **V**>

Acceptable Short or Non-Descriptive Names
-----------------------------------------

* Type parameter names of generic functions may be single characters:

  .. parsed-literal::

    func swap<**T**>(lhs: inout T, rhs: inout T)

* `lhs` and `rhs` are acceptable names for binary operator or
  symmetric binary function parameters:

  .. parsed-literal::

    func + (**lhs**: Int, **rhs**: Int) -> Int

    func swap<T>(**lhs**: inout T, **rhs**: inout T)

* `body` is an acceptable name for a trailing closure argument when
  the resulting construct is supposed to act like a language extension
  and is likely to have side-effects::

    func map<U>(_ transformation: T->U) -> [U] // not this one

    func forEach<S: SequenceType>(_ body: (S.Iterator.Element) -> ())

Prefixes and Suffixes
---------------------

* `Any` is used as a prefix to denote "type erasure,"
  e.g. `AnySequence<T>` wraps any sequence with element type `T`,
  conforms to `SequenceType` itself, and forwards all operations to the
  wrapped sequence.  When handling the wrapper, the specific type of
  the wrapped sequence is fully hidden.

* `Custom` is used as a prefix for special protocols that will always
  be dynamically checked for at runtime and don't make good generic
  constraints, e.g. `CustomStringConvertible`.

* `InPlace` is used as a suffix to denote the mutating member of a
  pair of related methods:

  .. parsed-literal::

    extension Set {
      func union(_ other: Set) -> Set
      mutating func union\ **InPlace**\ (_ other: Set)
    }

* `with` is used as a prefix to denote a function that executes a
  closure within a context, such as a guaranteed lifetime:

  .. parsed-literal::

     s.\ **with**\ CString {
       let fd = fopen($0)
       ...
     } // don't use that pointer after the closing brace

* `Pointer` is used as a suffix to denote a non-class type that acts
  like a reference, c.f. `ManagedBufferPointer`

* `unsafe` or `Unsafe` is *always* used as a prefix when a function or
  type allows the user to violate memory or type safety, except on
  methods of types whose names begin with `Unsafe`, where the type
  name is assumed to convey that.

* `C` is used as a prefix to denote types corresponding to C language
  types, e.g. `CChar`.