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

Chapter 18: Patterns #469

Merged
merged 22 commits into from
Apr 10, 2017
Merged

Chapter 18: Patterns #469

merged 22 commits into from
Apr 10, 2017

Conversation

steveklabnik
Copy link
Member

@steveklabnik steveklabnik commented Feb 23, 2017

Fixes #468 (I ended up using the last example, we should give credit)

Fixes #298 by discussing destructuring, ref, and more complex patterns.

println!("The value of y is: {}", y);
}
Here, we have a tuple that we're matching against a pattern. Rust will compare
the value `(1, 2, 3)` to the pattern `(x, y, z)`, and see that it's valid. In

Choose a reason for hiding this comment

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

Just realised you do this in the concurrency chapter when creating a channel. We may want to mention this chapter there, depending on how that chapter shakes out.

Copy link
Member

Choose a reason for hiding this comment

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

Good eyes!

the most commonly used ones in this section. Any of these abilities work in any
place where a pattern is used.
One of Rust's more subtle features is the simple *pattern*. Patterns let us
pick apart complex strucutres and do all kinds of fun things with them. In this

Choose a reason for hiding this comment

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

strucutres => structures

And run it with `cargo run`:
Where we nest tons of things inside of each other.

## Refutability

Choose a reason for hiding this comment

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

Can we move this section lower? It feels like I want more hands-on with working with patterns before we get into the peculiarities of them.

familliar with the word when you see it, and realize that you need to change
either the pattern, or the construct you're using the pattern with.

## Where can I use patterns?

Choose a reason for hiding this comment

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

Also if let

In simple cases like this, two `let`s may be clearer, but in others, creating
multiple variables at once is nice. As we become more proficient in Rust, we’ll
figure out which style is better, but it’s mostly a judgment call.
These patterns are refuatble. However...

Choose a reason for hiding this comment

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

refuatble => refutable

In simple cases like this, two `let`s may be clearer, but in others, creating
multiple variables at once is nice. As we become more proficient in Rust, we’ll
figure out which style is better, but it’s mostly a judgment call.
These patterns are refuatble. However...

Choose a reason for hiding this comment

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

I'm wondering if we could say let and match must cover all cases that the value can be. We can introduce the terms for this later, as I think they're less interesting than the concept of patterns matching values

## Literals & _
Here's a list of all of the different types of patterns.

### Literals & _

You can match against literals directly, and `_` acts as an ‘any’ case:

Choose a reason for hiding this comment

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

this is rendering for me as �any�

Copy link
Member

Choose a reason for hiding this comment

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

your comment is rendering for me as �any�

Copy link
Member

Choose a reason for hiding this comment

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

I think i found all of these?

## Literals & _
Here's a list of all of the different types of patterns.

### Literals & _

Choose a reason for hiding this comment

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

We may want to say "the underscore (_) pattern"

@@ -178,7 +280,7 @@ match name {
println!("name is: {:?}", name);
```

## Destructuring
### Destructuring

Choose a reason for hiding this comment

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

Destructuring mentions structs and enums, but only shows structs.

Since you're quite often going to use pattern matching against enums, we probably want to cover them again here.

```

In this case, we want to compare `id` against the range `3...7`, but we also
want to save the actual value of `id`.

Choose a reason for hiding this comment

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

Do we want a summary?

Copy link
Member

Choose a reason for hiding this comment

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

yep

@sophiajt
Copy link

This one feels like a reference rather than the narrative style of the rest of the book. Perhaps that's mostly okay, but I think we should at least chat about whether or not we want the narrative style here as well.

@carols10cents
Copy link
Member

@steveklabnik @jonathandturner I rearranged this a bunch, better or worse?

I like this chapter as a reference; trying to think of an example or use case that could weave through this whole chapter seems hard and like we'd end up with a gargantuan match with a million arms :octocat: 🐙

@steveklabnik some of the TODOs in here are places that I think we could use some more text, could you take care of those please, or let me know if you'd rather I do it?

@steveklabnik
Copy link
Member Author

TODO: if let example that isn't too repetitive with ch06-03

The problem here is that almost all uses of if let are those ones; I
grepped the compiler and 99% of them are either "do something on Some/None" or
"do something on one variant of an enum." I did have an interesting example in
the chapter 20, but then this would be duplicate of that...

@steveklabnik
Copy link
Member Author

TODO: but not floating point literals right?

Sure, that works too.

TODO: would you consider references with & as a sort of literal? or is that
more like destructuring?

Only if the value itself is a literal, that is, &5 is a literal match, &n is a destructuring.

@steveklabnik
Copy link
Member Author

I've pushed up some TODO fixes; @carols10cents if you get the chance, feel free to wrap this up; if not, I'll try to take another look soon.

@carols10cents
Copy link
Member

TODO: but not floating point literals right?

Sure, that works too.

I'm so confused right now. In my research for this chapter, I found this tracking issue (still open but partially complete) and this merged RFC which seem to imply that attempting to use floating point literals in match arms should produce a warning and in the future will be a hard error.

However, this code does not give me any warnings and seems to work happily.

It's only if I put the floating point in a constant that I can trigger the error mentioned.

Why are floating point literals allowed but not floating point constants? From the discussion on the RFC and linked threads, it's floating point numbers only implementing PartialEq and not Eq that's the problem, so shouldn't these both be disallowed?

Did I find a bug or am I misunderstanding something...?

@carols10cents
Copy link
Member

OK, I'm ignoring whether or not you're supposed to be allowed to match floating point literals, and I think this is ready for review.

@steveklabnik @jonathandturner @ScottAbbey @matthewjasper ? ❤️ Anyone else? ❤️

fail to match for some possible value are said to be *refutable*. `let`
statements, function parameters, and `for` loops are restricted to only accept
irrefutable patterns, since there's nothing correct the program could do if the
pattern fails to match. `match`, `if let`, and `while let` expressions are
Copy link
Contributor

@matthewjasper matthewjasper Apr 8, 2017

Choose a reason for hiding this comment

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

Not match. As this section says later: 'the last arm that might match any remaining values with an irrefutable pattern'.

`Some(y)` introduces a new variable name `y` that will match any value inside a
`Some` value. Because we're in a new scope inside the `match` expression, this
is a new variable, not the `y` we declared at the beginning that has the value
10. The new `y` binding will match any value inside a `Some`, which is what we
Copy link
Contributor

@matthewjasper matthewjasper Apr 8, 2017

Choose a reason for hiding this comment

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

Sigh... 'value' needs to be moved down to this line.

Copy link
Member

Choose a reason for hiding this comment

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

aaaiiiieeee


### Multiple patterns

You can match multiple patterns with `|`, which means *or*:
Copy link
Contributor

Choose a reason for hiding this comment

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

This is for match only. Perhaps that could be clearer.


### Matching Ranges of Values with `...`

You can match a range of values with `...`:
Copy link
Contributor

Choose a reason for hiding this comment

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

(inclusive)


match p {
Point { x, y: 0 } => println!("On the x axis at {}", x),
Point { x: 0, y} => println!("On the y axis at {}", y),
Copy link
Contributor

Choose a reason for hiding this comment

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

space between y and }?

# }
#
let points = vec![
Point { x: 0, y: 0},
Copy link
Contributor

Choose a reason for hiding this comment

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

Space before } (and following two lines)?

let _s = s;

println!("{}", s);
```
Copy link
Contributor

Choose a reason for hiding this comment

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

Would this and the next example be more helpful if they showed this in a match/if let, like 18-16.


This works just fine. Because we never bind `s` to anything, it's not moved.

### Ignoring Remaining Parts of a Value with `..`
Copy link
Contributor

Choose a reason for hiding this comment

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

Should have 4 '#'?

`robot_name` is moved within the `match` when `name` binds to that value.

Using `&` in a pattern matches an existing reference in the value, as we saw in
the previous section on destructuring. If you want to create a reference
Copy link
Contributor

Choose a reason for hiding this comment

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

'a previous section'?

Copy link
Member

Choose a reason for hiding this comment

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

I used "the" to refer to the specific section; I'm changing this to have the section heading to be clearer which section we're referring to 👍

<span class="caption">Listing 18-21: Ignoring all fields of a `Point` except
for `x` by using `..`</span>

Using `..` is shorter to type than having to list out `_y` and `_z`. The `..`
Copy link
Contributor

Choose a reason for hiding this comment

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

y: _ and z: _

Copy link
Member

Choose a reason for hiding this comment

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

lol idk why I thought i could combine the shorthand struct syntax and underscores....

Copy link
Member Author

@steveklabnik steveklabnik left a comment

Choose a reason for hiding this comment

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

💯 some very small typo things


The first call to `enumerate` produces the tuple `(0, 1)`. When this value is
matched to the pattern `(index, value)`, `index` will be 0 and `value` will
equal 1.
Copy link
Member Author

Choose a reason for hiding this comment

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

s/equal/be/, that is, changing the verb in the middle of the sentence feels weird to me (so we could also change 'be' to 'equal' on the line above and i'd be fine either way

let x = 5;
```

We've done this hundreds of times throughout this book. You may not have
Copy link
Member Author

Choose a reason for hiding this comment

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

don't we know it


With `let`, we compare the expression against the pattern, and assign any names
we find. So for example, in our `let x = 5;` case, `x` is a pattern that says
"bind what matches here to the variable `x`. And since the name `x` is the
Copy link
Member Author

Choose a reason for hiding this comment

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

need a " after the .

## Refutability: Whether a Pattern Might Fail to Match

Patterns come in two forms: refutable and irrefutable. Patterns which cannot
fail to match for any possible value are *irrefutable*, and patterns which can
Copy link
Member Author

Choose a reason for hiding this comment

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

"are said to be" so this matches up with the latter part of the sentence

println!("Found some other id: {}", id)
},
}
```
Copy link
Member Author

Choose a reason for hiding this comment

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

👍 😍 zomg i have not found an example this good in years of trying, every @ example I've seen has been to complex

@carols10cents carols10cents mentioned this pull request Apr 10, 2017
16 tasks
@carols10cents carols10cents merged commit 73c1a0d into master Apr 10, 2017
@carols10cents carols10cents deleted the ch18-patterns branch April 10, 2017 15:34
@rambip
Copy link

rambip commented Jul 11, 2023

I'm surprised there is no explanation about the ref syntax: it seems it is a quite isefull part of pattern matching !

Even other books use it, see here

Am I missing something here ?

It deserves an entire page IMO

If someone adds an explanation in chapter 18, it would be usefull to add a link from "deref" or pointers more broadly to this explanation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants