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