[swift-evolution] [DRAFT] Regularizing Where Grammar (was Re: Add a while clause to for loops)

Rob Norback rnorback at gmail.com
Fri Jun 10 14:06:09 CDT 2016


Following Brent's logic that the for-in where should mimic the switch
statement functionality, then this example:

for (eachKey, eachValue)
where eachValue > 5
in theKeyValuePairs {... }

Should read like:

for (eachKey, eachValue where eachValue > 5) in theKeyValuePairs {... }

And,

for (eachKey, eachValue)
where eachKey % 2 == 0 && eachValue > 5
in theKeyValuePairs {... }

Should read like:

for (eachKey where eachKey % 2 == 0, eachValue where eachValue > 5)
in theKeyValuePairs {... }

Personally, I think the first examples are much more readable. But if we go
with the proposal as it stands, we will be creating yet another syntax
structure for where.

Just wanted to point that out.



On Fri, Jun 10, 2016 at 11:06 AM Brent Royal-Gordon via swift-evolution <
swift-evolution at swift.org> wrote:

> > 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160610/3f6b8760/attachment.html>


More information about the swift-evolution mailing list