Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
92 lines (70 sloc) 4.9 KB

Closure Parameter Names and Labels

Revision History

  • v1 (as proposed)
  • v2: fixed spelling of identifiers containing Utf8 to read UTF8 per convention.

Introduction

We propose a revision to the names and argument labels of closure parameters in standard library APIs.

Swift-evolution thread: Take 2: Stdlib closure argument labels and parameter names

Discussion of earlier revision of the proposal: Stdlib closure argument labels and parameter names

Motivation

The names and argument labels of the standard library's closure parameters have been chosen haphazardly, resulting in documentation comments that are inconsistent and often read poorly, and in code completion/documentation that is less helpful than it might be. Because of trailing closure syntax, the choice of argument labels for closures has less impact on use-sites than it might otherwise, but there are many contexts in which labels still do appear, and poorly-chosen labels still hurt readability.

Proposed Solution

The table below summarizes how this proposal changes usage of the APIs in question.

Before After

s.withUTF8Buffer(invoke: processBytes)

s.withUTF8Buffer(processBytes)

lines.split(
  isSeparator: isAllWhitespace)

lines.split(
  whereSeparator: isAllWhitespace)

words.sort(isOrderedBefore: >)

words.sort(by: >)

words.sorted(isOrderedBefore: >)

words.sorted(by: >)

smallest = shapes.min(
  isOrderedBefore: haveIncreasingSize)

smallest = shapes.min(
  by: haveIncreasingSize)

largest = shapes.max(
  isOrderedBefore: haveIncreasingSize)

largest = shapes.max(
  by: haveIncreasingSize)

if a.lexicographicallyPrecedes(
  b,
  isOrderedBefore: haveIncreasingWeight)

if a.lexicographicallyPrecedes(
  b, by: haveIncreasingWeight)

ManagedBuffer<Header,Element>.create(
  minimumCapacity: 10,
  initialValue: makeHeader)

ManagedBuffer<Header,Element>.create(
  minimumCapacity: 10,
  makingValueWith: makeHeader)

if roots.contains(isPrime) {

if roots.contains(where: isPrime) {

if expected.elementsEqual(
  actual, isEquivalent: haveSameValue)

if expected.elementsEqual(
  actual, by: haveSameValue)

if names.starts(
  with: myFamily,
  isEquivalent: areSameExceptForCase) {

if names.starts(
  with: myFamily,
  by: areSameExceptForCase) {

let sum = measurements.reduce(0, combine: +)

let sum = measurements.reduce(0, +)

UTF8.encode(
  scalar, sendingOutputTo: accumulateByte)

UTF8.encode(
  scalar, into: accumulateByte)

Note: this summary does not illustrate parameter name changes that have also been made pervasively and have an effect on usability of documentation and code completion. Please see the diffs for examples of those.

Detailed design

A complete patch, showing API, documentation, and usage changes, is available for review at https://github.com/apple/swift/pull/2981/files.

Impact on existing code

This change will break code that depends on the current argument labels. Availability annotations can be used make correcting this breakage a normal part of the migration process.

Alternatives considered

The initial proposal used much more-verbose labels that were designed to be very explicit about the required semantics of the closure parameters. That information, however, is mostly useful to the author of the call, and, we found, didn't do much to enhance readability at the point of use.

Future Extensions (Out of Scope)

The process of making these changes revealed that there are compelling arguments for diverging from terms-of-art for the standard functional methods. For example, the polarity of the argument to filter would be crystal clear if it were renamed to where, and the description of the semantics of reduce in the documentation strongly suggest that accumulated might be an improvement. Changing the names of these methods should be considered in a separate proposal.