[swift-evolution] [Review] SE-0081: Move where clause to end of declaration

Pyry Jahkola pyry.jahkola at iki.fi
Sat May 14 14:43:37 CDT 2016

Tony & Haravikk,

(Reformatting your quoted examples just a bit…)

>> It enables things like:
>>     func someMethod<S : SequenceType, T>(value: S) -> AnySequence<T>
>>         where S.Generator.Element == T { ... }
> I'm not assuming that. Under the current syntax, I would format your example as:
>     func someMethod<
>         S : SequenceType, T
>         where S.Generator.Element == T
>     >(value: S) -> AnySequence<T> {
>         ...
>     }

You are both right here, but please note that the proposal still also allows moving all constraints to the `where` clause:

    func someMethod<S, T>(value: S) -> AnySequence<T>
        where S : SequenceType,
              S.Generator.Element == T

just like Swift 2 allows doing so within the `<...>` brackets:

    func someMethod<S, T
        where S : SequenceType, S.Generator.Element == T
    >(value: S) -> AnySequence<T> {

The reason I'd recommend that style for anything but simple constraints is because:

1) It makes the call site `let items = someMethod(value: things)` lightest to visually match to the declaration, because the only thing between the function name and its argument list is the `<...>` bracketed list of introduced generic types which you'll expect to see in the function signature and constraints.

2) In general, the `where` constraints really apply to the whole function/type declaration, not just a single generic parameter.

3) It was claimed that all constraints should go right next to the introduction of the generic parameters. But that isn't the whole case because Swift also applies implicit constraints onto any generic parameters that are used in constrained positions. If that wasn't clearly said, take the following example in Swift 2.x:

    func aMethod<S : SequenceType, T where S.Generator.Element == T>(value: S) -> Set<T> {
        return Set(value)

That declaration actually makes you wait all the way until the return type `Set<T>` until you learn that `T` must also necessarily be `Hashable`. So I don't see how it's that different if the `where` clause isn't right next to the generic type arguments' introduction:

    func aMethod<S, T>(value: S) -> Set<T> // FWIW, this line contains what I usually have in mind when browsing code.
        where // T : Hashable, // (implicit)
              S : SequenceType,
              S.Generator.Element == T
        return Set(value)

— Pyry

PS. Besides, neither the original example nor mine was really fair; you don't need `where` for these. Instead, you'd just write:

    func someMethod<S : SequenceType>(value: S) -> AnySequence<S.Generator.Element> {

which SE-0081 has nothing to argue for or against.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160514/aedc8c76/attachment.html>

More information about the swift-evolution mailing list