@@ -707,99 +707,14 @@ ignore thereafter. This code could mean that we want to ignore `2`, bind
707
707
The variable name ` second ` doesn’t mean anything special to Rust, so we get a
708
708
compiler error because using ` .. ` in two places like this is ambiguous.
709
709
710
- ### Creating References in Patterns with ` ref ` and ` ref mut `
711
-
712
- Let’s look at using ` ref ` to make references so ownership of the values isn’t
713
- moved to variables in the pattern. Usually, when you match against a pattern,
714
- the variables introduced by the pattern are bound to a value. Rust’s ownership
715
- rules mean the value will be moved into the ` match ` or wherever you’re using
716
- the pattern. Listing 18-26 shows an example of a ` match ` that has a pattern
717
- with a variable and then usage of the entire value in the ` println! ` statement
718
- later, after the ` match ` . This code will fail to compile because ownership of
719
- part of the ` robot_name ` value is transferred to the ` name ` variable in the
720
- pattern of the first ` match ` arm.
721
-
722
- ``` rust,ignore
723
- let robot_name = Some(String::from("Bors"));
724
-
725
- match robot_name {
726
- Some(name) => println!("Found a name: {}", name),
727
- None => (),
728
- }
729
-
730
- println!("robot_name is: {:?}", robot_name);
731
- ```
732
-
733
- <span class =" caption " >Listing 18-26: Creating a variable in a ` match ` arm
734
- pattern takes ownership of the value</span >
735
-
736
- Because ownership of part of ` robot_name ` has been moved to ` name ` , we can no
737
- longer use ` robot_name ` in the ` println! ` after the ` match ` because
738
- ` robot_name ` no longer has ownership.
739
-
740
- To fix this code, we want to make the ` Some(name) ` pattern * borrow* that part
741
- of ` robot_name ` rather than taking ownership. You’ve already seen that, outside
742
- of patterns, the way to borrow a value is to create a reference using ` & ` , so
743
- you might think the solution is changing ` Some(name) ` to ` Some(&name) ` .
744
-
745
- However, as you saw in the “Destructuring to Break Apart Values” section, the
746
- syntax ` & ` in patterns does not * create* a reference but * matches* an existing
747
- reference in the value. Because ` & ` already has that meaning in patterns, we
748
- can’t use ` & ` to create a reference in a pattern.
749
-
750
- Instead, to create a reference in a pattern, we use the ` ref ` keyword before
751
- the new variable, as shown in Listing 18-27.
752
-
753
- ``` rust
754
- let robot_name = Some (String :: from (" Bors" ));
755
-
756
- match robot_name {
757
- Some (ref name ) => println! (" Found a name: {}" , name ),
758
- None => (),
759
- }
760
-
761
- println! (" robot_name is: {:?}" , robot_name );
762
- ```
763
-
764
- <span class =" caption " >Listing 18-27: Creating a reference so a pattern variable
765
- does not take ownership of a value</span >
766
-
767
- This example will compile because the value in the ` Some ` variant in
768
- ` robot_name ` is not moved into the ` match ` ; the ` match ` only took a reference
769
- to the data in ` robot_name ` rather than moving it.
770
-
771
- To create a mutable reference so we’re able to mutate a value matched in a
772
- pattern, we use ` ref mut ` instead of ` &mut ` . The reason is, again, that in
773
- patterns, the latter is for matching existing mutable references, not creating
774
- new ones. Listing 18-28 shows an example of a pattern creating a mutable
775
- reference.
776
-
777
- ``` rust
778
- let mut robot_name = Some (String :: from (" Bors" ));
779
-
780
- match robot_name {
781
- Some (ref mut name ) => * name = String :: from (" Another name" ),
782
- None => (),
783
- }
784
-
785
- println! (" robot_name is: {:?}" , robot_name );
786
- ```
787
-
788
- <span class =" caption " >Listing 18-28: Creating a mutable reference to a value as
789
- part of a pattern using ` ref mut ` </span >
790
-
791
- This example will compile and print ` robot_name is: Some("Another name") ` .
792
- Because ` name ` is a mutable reference, we need to dereference within the match
793
- arm code using the ` * ` operator to mutate the value.
794
-
795
710
### Extra Conditionals with Match Guards
796
711
797
712
A * match guard* is an additional ` if ` condition specified after the pattern in
798
713
a ` match ` arm that must also match, along with the pattern matching, for that
799
714
arm to be chosen. Match guards are useful for expressing more complex ideas
800
715
than a pattern alone allows.
801
716
802
- The condition can use variables created in the pattern. Listing 18-29 shows a
717
+ The condition can use variables created in the pattern. Listing 18-26 shows a
803
718
` match ` where the first arm has the pattern ` Some(x) ` and also has a match
804
719
guard of ` if x < 5 ` .
805
720
@@ -813,7 +728,7 @@ match num {
813
728
}
814
729
```
815
730
816
- <span class =" caption " >Listing 18-29 : Adding a match guard to a pattern</span >
731
+ <span class =" caption " >Listing 18-26 : Adding a match guard to a pattern</span >
817
732
818
733
This example will print ` less than five: 4 ` . When ` num ` is compared to the
819
734
pattern in the first arm, it matches, because ` Some(4) ` matches ` Some(x) ` . Then
@@ -852,7 +767,7 @@ fn main() {
852
767
}
853
768
```
854
769
855
- <span class =" caption " >Listing 18-30 : Using a match guard to test for equality
770
+ <span class =" caption " >Listing 18-27 : Using a match guard to test for equality
856
771
with an outer variable</span >
857
772
858
773
This code will now print ` Default case, x = Some(5) ` . The pattern in the second
@@ -884,7 +799,7 @@ match x {
884
799
}
885
800
```
886
801
887
- <span class =" caption " >Listing 18-31 : Combining multiple patterns with a match
802
+ <span class =" caption " >Listing 18-18 : Combining multiple patterns with a match
888
803
guard</span >
889
804
890
805
The match condition states that the arm only matches if the value of ` x ` is
@@ -941,7 +856,7 @@ match msg {
941
856
}
942
857
```
943
858
944
- <span class =" caption " >Listing 18-32 : Using ` @ ` to bind to a value in a pattern
859
+ <span class =" caption " >Listing 18-19 : Using ` @ ` to bind to a value in a pattern
945
860
while also testing it</span >
946
861
947
862
This example will print ` Found an id in range: 5 ` . By specifying `id_variable
@@ -963,6 +878,66 @@ first two arms: any value would match this pattern.
963
878
964
879
Using ` @ ` lets us test a value and save it in a variable within one pattern.
965
880
881
+ ### Legacy patterns: ` ref ` and ` ref mut `
882
+
883
+ In older versions of Rust, ` match ` would assume that you want to move what is
884
+ matched. But sometimes, that's not what you wanted. For example:
885
+
886
+ ``` rust
887
+ let robot_name = & Some (String :: from (" Bors" ));
888
+
889
+ match robot_name {
890
+ Some (name ) => println! (" Found a name: {}" , name ),
891
+ None => (),
892
+ }
893
+
894
+ println! (" robot_name is: {:?}" , robot_name );
895
+ ```
896
+
897
+ Here, ` robot_name ` is a ` &Option<String> ` . Rust would then complain that
898
+ ` Some(name) ` doesn't match up with ` &Option<T> ` , so you'd have to write this:
899
+
900
+ ``` rust
901
+ let robot_name = & Some (String :: from (" Bors" ));
902
+
903
+ match robot_name {
904
+ & Some (name ) => println! (" Found a name: {}" , name ),
905
+ None => (),
906
+ }
907
+
908
+ println! (" robot_name is: {:?}" , robot_name );
909
+ ```
910
+
911
+ Next, Rust would complain that ` name ` is trying to move the ` String ` out of
912
+ the option, but because it's a reference to an option, it's borrowed, and so
913
+ can't be moved out of. This is where the ` ref ` keyword comes into play:
914
+
915
+ ``` rust
916
+ let robot_name = & Some (String :: from (" Bors" ));
917
+
918
+ match robot_name {
919
+ & Some (ref name ) => println! (" Found a name: {}" , name ),
920
+ None => (),
921
+ }
922
+
923
+ println! (" robot_name is: {:?}" , robot_name );
924
+ ```
925
+
926
+ The ` ref ` keyword is like the opposite of ` & ` in patterns; this says "please
927
+ bind ` ref ` to be a ` &String ` , don't try to move it out. In other words, the
928
+ ` & ` in ` &Some ` is matching against a reference, but ` ref ` * creates* a
929
+ reference. ` ref mut ` is like ` ref ` , but for mutable references.
930
+
931
+ Anyway, today's Rust doesn't work like this. If you try to ` match ` on
932
+ something borrowed, then all of the bindings you create will attempt to
933
+ borrow as well. This means that the original code works as you'd expect.
934
+
935
+ Because Rust is backwards compatible, we couldn't remove ` ref ` and ` ref mut ` ,
936
+ and they're sometimes useful in obscure situations, where you want to
937
+ partially borrow part of a struct as mutable and another part as immutable.
938
+ But you may see them in older Rust code, so knowing what they do is still
939
+ useful.
940
+
966
941
## Summary
967
942
968
943
Rust’s patterns are very useful in that they help distinguish between different
0 commit comments