Discussion has quiesced a little, but I had some more thoughts around the proposed each
syntax, having to do with names.
That said, I’m going to fold it away because (1) it’s more bikeshedding, and (2) it’s an argument about what’s ‘natural-sounding’ to a native English speaker, and while that can encourage correct usage it should never be our most important goal. After all, we have many non-native-English-speaker users of Swift.
The repeat
syntax is pretty obviously important: it indicates the type or expression being repeated. You could spell it differently, but some form of it is needed. each
, however, has felt redundant in many of the examples; if it were omitted, the compiler would easily detect that something went wrong, and even know exactly how to correct it if repeat
were already present.
The cycle seems to be 'we need these symbols to clarify what types of things we're referring to!' followed by 'wait, it turns out words already do that.' [xkcd: Sigil Cycle]
A lot of these examples have used each T
as the name of the type parameter pack, and yeah, sometimes there’s no better name. But usually Swift tries to go for something better than that, and we therefore have a choice of whether a name should be singular or plural. (This was brought up in the pitch phase as well, when the working syntax still used ellipses like C++.)
There are three relevant names: the declared type parameter pack; the “nouny” name of a value parameter pack, property pack, or local binding pack; and the “verb-or-prepositiony” name of a “fluent”, “reads-like-a-sentence” function name or argument label. The last one, fortunately, is trivial in English: both verbs and prepositions do not change based on whether the object is plural (“consume an apple” vs “consume apples”; “into the box” vs “into the boxes”). The first one reads very well with each
if it’s written using a singular noun: each Subview: View
(“each subview is a View”), (repeat Optional<each Input>) -> Bool
(“a function where you repeat Optional<_>
for each input and return a boolean”).
But the second one is a problem, because parameter names (and nouny argument labels) really want to be plural:
/// - subviews: One or more views to include within this view
findFirstMatching(candidates: apple, orange, goat) { preventsScurvy($0) }
Both of those would read worse to a native English speaker in singular form. We could allow writing parameters as each subview
in documentation, but nouny argument labels still show up enough that I don’t think we should disregard this.
This is too bad, because I like each
. It has pretty good connotations for me within repeat
and in the repeat
-less syntax proposed for constraints (though now that it’s been pointed out that does seem odd to me too). But I think these things want to be plural for clarity in documentation and at the call site, and that means each
no longer fits for me.
(Unfortunately, I cannot think of what would; remember, the important use is not when you declare the type pack, but within repeat
, that goes from a plural to a singular. Perhaps this is why Python forces you to name the element in a list comprehension, instead of making the expression based on the name of an existing iterator.)
// Terrible exploration showing where 'each' is used
func process<pack Subviews>(subviews: repeat Optional<unpack Subviews>)
where repeat unpack Subviews: View {
let labels: repeat String = repeat (unpack subviews)?.label ?? ""
// …
}