Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] RFC: or patterns #12

Closed
wants to merge 19 commits into from
Closed

[DRAFT] RFC: or patterns #12

wants to merge 19 commits into from

Conversation

Centril
Copy link
Owner

@Centril Centril commented Aug 29, 2018

This is a draft version of an RFC for you to review, before a formal proposal is made for consideration.

r: Option<i32>) -> ParseResult<Option<i32>> {
match (y, q, r) {
(y, None, None) => Ok(y),
(Some(y), q, r @ (Some(0...99) None)) => { ... },
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing | between the Some and None (I assume, Sourcegraph appears to not be Safari compatible so I can't view the original)


```rust
match (op, &mmp.clone()) {
(&Lt, &M(0) | &MM(0, 0) | &MMP(0, 0, 0)) => debcargo_bail!(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be simplified slightly more to (&Lt, &(M(0) | MM(0, 0) | MMP(0, 0, 0))) (and similar for the other branches).


+ the type inferred for `p` does not unify with the type inferred for `q`, or
+ the same set of bindings are not introduced in `p` and `q`, or
+ the type two bindings with the same name in `p` and `q` do not unify.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing something between "type two", maybe "the type of any two bindings"?

Thus, we conjecture that it's more common for humans to not distribute and to
instead use something akin to *conjunctive normal form* ([CNF]) when communicating.
A likely consequence of this is that a common way to understand snippet (1)
formulated in [DNF] is to first mentally reconstruct it into CNF and then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing the expansion for DNF


Here `|` has the lowest precedence.
In particular, the operator `@` binds more tightly than `|` does.
Thus, `i @ p | q` associates as `i @ (p | q)` as opposed to `(i @ p) | q`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems inconsistent with the precedence shown elsewhere in the RFC.


Allow `|` to be arbitrarily nested within a pattern such
that `Some(A(0) | B(1 | 2))` becomes a valid pattern.
The operator `|` has low precedence such that `i @ p | q` means `(i @ p) | q`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you cross-reference the explanation of this precedence? My first instinct was to prefer to see @ as the lowest-precedence thing in patterns, unless there's some specific compatibility reason to do otherwise, but at the same time I could readily be convinced otherwise if you have a rationale for this.

Also, I don't think you need to put the precedence in the summary; you can put it later in the document.

+ Farsi (3)
+ Finnish (1)
+ Esperanto (1)
+ Japanese (1)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This is a fun detail, but I don't think it needs to be a bulleted list; just inline it as a flat comma-separated list in the sentence.

[RFC 2175]: https://github.com/rust-lang/rfcs/pull/2175

In concrete terms, where before we only allowed a pattern of the form
`'|'? pat | pat` at the top level of `match` and [similar constructs][RFC 2175],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think including the optional leading vert here obfuscates the point you're trying to make. Just say pat | pat in both places.


6. Some further examples found with sourcegraph include:

From [cc-rs](https://sourcegraph.com/github.com/alexcrichton/cc-rs/-/blob/src/lib.rs#L1307:18):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For all of these citation links, please link to a specific commit hash, so that the line number references remain working in the future.

```

Note that the operator `|` has a low precedence. This means that you
have to write `foo @ (1 | 2 | 3)` instead of writing `foo @ 1 | 2 | 3`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This phrasing seems confusing; "you have to write" suggests that this is what you'd want in the common case, in which case let's set the precedence to make that case easier to write.


+ the type inferred for `p` does not unify with the type inferred for `q`, or
+ the same set of bindings are not introduced in `p` and `q`, or
+ the type of any two bindings with the same name in `p` and `q` do not unify.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or the binding mode; for instance, if you bind the same name as mut in p and non-mut in q.

in CNF to its equivalent form in DNF, i.e. `c(p) | c(q)`.

However, implementing `c(p | q)` in terms of a pure desugaring to `c(p) | c(q)`
may not be optimal as the desugaring can result in exponential blow-up of patterns.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please give a concrete example here. (Also, s/exponential/multiplicative/.)

For an example, (0|1, 0|1, 0|1, 0|1, ...) seems like the simplest one to understand.

this change should be done rather than *if*.

With respect to the precedence of `|`, we already cannot interpret `i @ p | q`
as `i @ (p | q)` because it is already legal to write `i @ p | j @ q`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an "at the top level of a pattern" here, to make it clear that this kind of alternation currently only works at the top level?

as `i @ (p | q)` because it is already legal to write `i @ p | j @ q`.
Therefore, if we say that `|` binds more tightly,
then `i @ p | j @ q` will associate as `i @ (p | j @ q)` which as a different
meaning than what we currently have, thus causing a breaking change.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, fair enough, this makes sense.

However, could you please specify a lint and suggestion for this? Specifically, if you write i @ p | q, you will already get an error because the two patterns (i@p and q) don't both bind i, so with a bit of extra error-reporting logic we could add a suggestion for i @ (p | q).

we should try to keep the language more uniform rather than less.
This is an important means through which it becomes possible to give users
more expressiveness but at the same time limit the cost each feature takes
from our complexity budget.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this whole paragraph. I'd love to see it added to some top-level documentation of the RFC repository, or some kind of language design philosophy document.

| |
| variable not in all patterns
|
| hint: if you wanted `i` to cover both cases, try adding parenthesis around:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"parentheses", plural.

@Centril
Copy link
Owner Author

Centril commented Aug 30, 2018

Thanks all! Time to :shipit:

@Centril Centril closed this Aug 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants