d.berg
d.berg

Reputation: 131

Naming convention for mutating functions in Swift

In Ruby, mutating methods (i.e. methods that modify self) are, by convention marked with a bang (!) to separate them from the similary named methods that do not modify self.

For instance Array#sort returns a sorted array, but Array#sort! modifies the array on which it is called.

I've now started looking into Swift. How would I name a mutating method to separate it from its non-mutating twin?

I know that Python has sorted(list) vs list.sort(). Is that a good pattern to follow, i.e .sorted() (non-mutating) and .sort() (mutating)?

How about names that are not readily transformed in that way, such as String#next vs String#next!?

Upvotes: 10

Views: 2454

Answers (1)

Cœur
Cœur

Reputation: 38667

About posting the official guidelines, here they are: https://swift.org/documentation/api-design-guidelines/#name-according-to-side-effects

Name Mutating/nonmutating method pairs consistently. A mutating method will often have a nonmutating variant with similar semantics, but that returns a new value rather than updating an instance in-place.

  • When the operation is naturally described by a verb, use the verb’s imperative for the mutating method and apply the “ed” or “ing” suffix to name its nonmutating counterpart.

    Mutating    Nonmutating
    x.sort()    z = x.sorted()
    x.append(y) z = x.appending(y)
    

    Prefer to name the nonmutating variant using the verb’s past participle (usually appending “ed”):

    /// Reverses `self` in-place.
    mutating func reverse()
    
    /// Returns a reversed copy of `self`.
    func reversed() -> Self
    ...
    x.reverse()
    let y = x.reversed()
    

    When adding “ed” is not grammatical because the verb has a direct object, name the nonmutating variant using the verb’s present participle, by appending “ing.”

    /// Strips all the newlines from `self`
    mutating func stripNewlines()
    
    /// Returns a copy of `self` with all the newlines stripped.
    func strippingNewlines() -> String
    ...
    s.stripNewlines()
    let oneLine = t.strippingNewlines()
    
  • When the operation is naturally described by a noun, use the noun for the nonmutating method and apply the “form” prefix to name its mutating counterpart.

    Nonmutating         Mutating
    x = y.union(z)      y.formUnion(z)
    j = c.successor(i)  c.formSuccessor(&i)
    

Ray Wenderlich sums it up in its own Swift Style Guide:

verb methods follow the -ed, -ing rule for the non-mutating version
noun methods follow the formX rule for the non-mutating version

Note that the official guidelines were updated for Swift 3 thanks to Proposal: SE-0059 by Dave Abrahams, Update API Naming Guidelines and Rewrite Set APIs Accordingly, after approval on 18th April 2016.

But five days before, on 13th April 2016, Erica Sadun expressed a somewhat different opinion in her article Stop the Madness and fix the Swift API guidelines. Let's add that Erica previously wrote her own article on the matter, Naming Methods and Functions, also available in her book Swift Style. And for the fun, she attempted to explain mutating naming with emoji.

Upvotes: 13

Related Questions