> I am curious, is there any conflict with the reasoning to move where here 
> compared to the accepted SE-0081 "Move where clause to end of declaration" 
> https://lists.swift.org/pipermail/swift-evolution-announce/2016-May/000161.html
> 
> We moved the where clause to before the body in one case (SE-0081) and now we 
> are trying to move the where clause from before the body to right next to the 
> variable. 
> 
> In SE-0081: "With the proposed change, where clauses do not impede the main 
> declaration and are also more easily formattable"
> 
> I know these are different uses but it is beginning to hurt my head where all 
> the where clauses are suppose to go in different contexts

I understand why this would confuse you, but there are practical reasons for 
them to be different.

The `where` clause is used in a couple different ways:

* In a declaration, it specifies additional type information—for instance, that 
an associated type conforms to a certain protocol or matches another associated 
type on a different type parameter.

        func append<C: Collection>(contentsOf other: C) where 
C.Iterator.Element == Self.Iterator.Element { … }

* In a `case` statement or other pattern, it specifies a Boolean condition 
which must be met for the pattern to match.

        switch value {
        case .result(let character) where emoji.contains(character):
                print("Hello, millennial!")
        case .result(_):
                print("Hello, fogey!")
        default:
                print("Goodbye, world!")
        }

Both versions of the clause refine a match to specify additional conditions; 
that's why they use the same keyword. But they're actually quite different.

In particular, one big difference between the two is that you can only attach 
one `where` clause to a declaration, but there might be many `where` clauses in 
a pattern match. For instance, in this example:

        enum X { case a, b }
        switch X.a {
        case .a, .b where 1 == 0:
                print("Matched")
        default:
                print("Didn't")
        }

The `where` clause only applies to the `.b`, not the `.a`, so the code will 
print "Matched". To make it print "Didn't", you'd have to write `case .a where 
1 == 0, .b where 1 == 0`. In other words, the `where` clause is part of the 
specific pattern, not the `case` statement as a whole, and so it *must* be 
attached to the specific pattern.

The `for` syntax, however, does not respect this rule. It inserts the `in` 
clause between the pattern (the thing after the `for` keyword is a pattern too, 
even if it doesn't have a `case` keyword) and its `where` clause. That's not 
consistent with `switch`-`case`'s syntax, and in practice, I find it leads to 
confusion about what `where` does.

For a declaration, however, there can only be one `where` clause, and you can 
equally well view it as applying to only the generic parameter list (the old 
way) or to the entire declaration (the new way). There are several reasons why 
it's very convenient to put it at the end:

1. Declaration `where` clauses tend to involve lots of verbose names and be 
very long.
2. Declaration `where` clauses sometimes need to be attached to declarations 
with no generic parameter list, like `extension` and hopefully soon 
`associatedtype`.
3. Declaration `where` clauses embedded in a generic parameter list end up 
wedging a bunch of usually unimportant information between two of the most 
important parts of the declaration: the list of generic parameters and the list 
of regular parameters. This ends up turning the whole thing into a jumbled mess.

So even though both kinds of `where` clause do broadly similar things, they 
face very different constraints and pressures, and thus are positioned a little 
bit differently. That's unfortunate, but probably unavoidable.

The proposal being discussed in this thread is actually trying to improve this 
situation by making pattern `where` clauses in `for` loops match pattern 
`where` clauses in `switch` statements. In other words, I believe it actually 
improves consistency over the status quo. So if you're confused about where you 
put `where`, this should make it a little easier to keep things straight.

-- 
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to