Skip to content

Latest commit

 

History

History
92 lines (70 loc) · 4.71 KB

0118-closure-parameter-names-and-labels.md

File metadata and controls

92 lines (70 loc) · 4.71 KB

Closure Parameter Names and Labels

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.


Rationale

On [Date], the core team decided to (TBD) this proposal. When the core team makes a decision regarding this proposal, their rationale for the decision will be written here.