@@ -948,11 +948,281 @@ comments
948948
949949## Compound Data Types
950950
951- Tuples
951+ Rust, like many programming languages, has a number of different data types
952+ that are built-in. You've already done some simple work with integers and
953+ strings, but next, let's talk about some more complicated ways of storing data.
952954
953- Structs
955+ ### Tuples
954956
955- Enums
957+ The first compound data type we're going to talk about are called ** tuple** s.
958+ Tuples are an ordered list of a fixed size. Like this:
959+
960+ ``` rust
961+ let x = (1i , " hello" );
962+ ```
963+
964+ The parenthesis and commas form this two-length tuple. Here's the same code, but
965+ with the type annotated:
966+
967+ ``` rust
968+ let x : (int , & str ) = (1 , " hello" );
969+ ```
970+
971+ As you can see, the type of a tuple looks just like the tuple, but with each
972+ position having a type name rather than the value. Careful readers will also
973+ note that tuples are heterogeneous: we have an ` int ` and a ` &str ` in this tuple.
974+ You haven't seen ` &str ` as a type before, and we'll discuss the details of
975+ strings later. In systems programming languages, strings are a bit more complex
976+ than in other languages. For now, just read ` &str ` as "a string slice," and
977+ we'll learn more soon.
978+
979+ You can access the fields in a tuple through a ** destructuring let** . Here's
980+ an example:
981+
982+ ``` rust
983+ let (x , y , z ) = (1i , 2i , 3i );
984+
985+ println! (" x is {}" , x );
986+ ```
987+
988+ Remember before when I said the left hand side of a ` let ` statement was more
989+ powerful than just assigning a binding? Here we are. We can put a pattern on
990+ the left hand side of the ` let ` , and if it matches up to the right hand side,
991+ we can assign multiple bindings at once. In this case, ` let ` 'destructures,'
992+ or 'breaks up,' the tuple, and assigns the bits to three bindings.
993+
994+ This pattern is very powerful, and we'll see it repeated more later.
995+
996+ The last thing to say about tuples is that they are only equivalent if
997+ the arity, types, and values are all identical.
998+
999+ ``` rust
1000+ let x = (1i , 2i , 3i );
1001+ let y = (2i , 3i , 4i );
1002+
1003+ if x == y {
1004+ println! (" yes" );
1005+ } else {
1006+ println! (" no" );
1007+ }
1008+ ```
1009+
1010+ This will print ` no ` , as the values aren't equal.
1011+
1012+ One other use of tuples is to return multiple values from a function:
1013+
1014+ ``` rust
1015+ fn next_two (x : int ) -> (int , int ) { (x + 1i , x + 2i ) }
1016+
1017+ fn main () {
1018+ let (x , y ) = next_two (5i );
1019+ println! (" x, y = {}, {}" , x , y );
1020+ }
1021+ ```
1022+
1023+ Even though Rust functions can only return one value, a tuple _ is_ one value,
1024+ that happens to be made up of two. You can also see in this example how you
1025+ can destructure a pattern returned by a function, as well.
1026+
1027+ Tuples are a very simple data structure, and so are not often what you want.
1028+ Let's move on to their bigger sibling, structs.
1029+
1030+ ### Structs
1031+
1032+ A struct is another form of a 'record type,' just like a tuple. There's a
1033+ difference: structs give each element that they contain a name, called a
1034+ 'field' or a 'member.' Check it out:
1035+
1036+ ``` rust
1037+ struct Point {
1038+ x : int ,
1039+ y : int ,
1040+ }
1041+
1042+ fn main () {
1043+ let origin = Point { x : 0i , y : 0i };
1044+
1045+ println! (" The origin is at ({}, {})" , origin . x, origin . y);
1046+ }
1047+ ```
1048+
1049+ There's a lot going on here, so let's break it down. We declare a struct with
1050+ the ` struct ` keyword, and then with a name. By convention, structs begin with a
1051+ capital letter and are also camel cased: ` PointInSpace ` , not ` Point_In_Space ` .
1052+
1053+ We can create an instance of our struct via ` let ` , as usual, but we use a `key:
1054+ value` style syntax to set each field. The order doesn't need to be the same as
1055+ in the original declaration.
1056+
1057+ Finally, because fields have names, we can access the field through dot
1058+ notation: ` origin.x ` .
1059+
1060+ The values in structs are immutable, like other bindings in Rust. However, you
1061+ can use ` mut ` to make them mutable:
1062+
1063+ ``` rust
1064+ struct Point {
1065+ x : int ,
1066+ y : int ,
1067+ }
1068+
1069+ fn main () {
1070+ let mut point = Point { x : 0i , y : 0i };
1071+
1072+ point . x = 5 ;
1073+
1074+ println! (" The point is at ({}, {})" , point . x, point . y);
1075+ }
1076+ ```
1077+
1078+ This will print ` The point is at (5, 0) ` .
1079+
1080+ ### Tuple Structs and Newtypes
1081+
1082+ Rust has another data type that's like a hybrid between a tuple and a struct,
1083+ called a ** tuple struct** . Tuple structs do have a name, but their fields
1084+ don't:
1085+
1086+
1087+ ```
1088+ struct Color(int, int, int);
1089+ struct Point(int, int, int);
1090+ ```
1091+
1092+ These two will not be equal, even if they have the same values:
1093+
1094+ ``` {rust,ignore}
1095+ let black = Color(0, 0, 0);
1096+ let origin = Point(0, 0, 0);
1097+ ```
1098+
1099+ It is almost always better to use a struct than a tuple struct. We would write
1100+ ` Color ` and ` Point ` like this instead:
1101+
1102+ ``` rust
1103+ struct Color {
1104+ red : int ,
1105+ blue : int ,
1106+ green : int ,
1107+ }
1108+
1109+ struct Point {
1110+ x : int ,
1111+ y : int ,
1112+ z : int ,
1113+ }
1114+ ```
1115+
1116+ Now, we have actual names, rather than positions. Good names are important,
1117+ and with a struct, we have actual names.
1118+
1119+ There _ is_ one case when a tuple struct is very useful, though, and that's a
1120+ tuple struct with only one element. We call this a 'newtype,' because it lets
1121+ you create a new type that's a synonym for another one:
1122+
1123+ ```
1124+ struct Inches(int);
1125+ struct Centimeters(int);
1126+
1127+ let length = Inches(10);
1128+
1129+ let Inches(integer_length) = length;
1130+ println!("length is {} inches", integer_length);
1131+ ```
1132+
1133+ As you can see here, you can extract the inner integer type through a
1134+ destructuring ` let ` .
1135+
1136+ ### Enums
1137+
1138+ Finally, Rust has a "sum type", an ** enum** . Enums are an incredibly useful
1139+ feature of Rust, and are used throughout the standard library. Enums look
1140+ like this:
1141+
1142+ ```
1143+ enum Ordering {
1144+ Less,
1145+ Equal,
1146+ Greater,
1147+ }
1148+ ```
1149+
1150+ This is an enum that is provided by the Rust standard library. An ` Ordering `
1151+ can only be _ one_ of ` Less ` , ` Equal ` , or ` Greater ` at any given time. Here's
1152+ an example:
1153+
1154+ ``` rust
1155+ let x = 5i ;
1156+ let y = 10i ;
1157+
1158+ let ordering = x . cmp (& y );
1159+
1160+ if ordering == Less {
1161+ println! (" less" );
1162+ } else if ordering == Greater {
1163+ println! (" greater" );
1164+ } else if ordering == Equal {
1165+ println! (" equal" );
1166+ }
1167+ ```
1168+
1169+ ` cmp ` is a function that compares two things, and returns an ` Ordering ` . The
1170+ call looks a little bit strange: rather than ` cmp(x, y) ` , we say ` x.cmp(&y) ` .
1171+ We haven't covered methods and references yet, so it should look a little bit
1172+ foreign. Right now, just pretend it says ` cmp(x, y) ` , and we'll get to those
1173+ details soon.
1174+
1175+ The ` ordering ` variable has the type ` Ordering ` , and so contains one of the
1176+ three values. We can then do a bunch of ` if ` /` else ` comparisons to check
1177+ which one it is.
1178+
1179+ However, repeated ` if ` /` else ` comparisons get quite tedious. Rust has a feature
1180+ that not only makes them nicer to read, but also makes sure that you never
1181+ miss a case. Before we get to that, though, let's talk about another kind of
1182+ enum: one with values.
1183+
1184+ This enum has two variants, one of which has a value.:
1185+
1186+ ```
1187+ enum OptionalInt {
1188+ Value(int),
1189+ Missing
1190+ }
1191+
1192+ fn main() {
1193+ let x = Value(5);
1194+ let y = Missing;
1195+
1196+ match x {
1197+ Value(n) => println!("x is {:d}", n),
1198+ Missing => println!("x is missing!"),
1199+ }
1200+
1201+ match y {
1202+ Value(n) => println!("y is {:d}", n),
1203+ Missing => println!("y is missing!"),
1204+ }
1205+ }
1206+ ```
1207+
1208+ This enum represents an ` int ` that we may or may not have. In the ` Missing `
1209+ case, we have no value, but in the ` Value ` case, we do. This enum is specific
1210+ to ` int ` s, though. We can make it usable by any type, but we haven't quite
1211+ gotten there yet!
1212+
1213+ You can have any number of values in an enum:
1214+
1215+ ```
1216+ enum OptionalColor {
1217+ Color(int, int, int),
1218+ Missing
1219+ }
1220+ ```
1221+
1222+ Enums with values are quite useful, but as I mentioned, they're even more
1223+ useful when they're generic across types. But before we get to generics, let's
1224+ talk about how to fix this big ` if ` /` else ` statements we've been writing. We'll
1225+ do that with ` match ` .
9561226
9571227## Match
9581228
0 commit comments