05 Rustlings Primitive Types Solution
Rust has a couple of basic types that are directly implemented into the compiler. In this section, we'll go through the most important ones.
Further information
Additional reading resources can be found here:
primitive_types1.rs
// primitive_types1.rs
// Fill in the rest of the line that has code missing!
// No hints, there's no tricks, just get used to typing these :)
// I AM NOT DONE
fn main() {
// Booleans (`bool`)
let is_morning = true;
if is_morning {
println!("Good morning!");
}
let // Finish the rest of this line like the example! Or make it be false!
if is_evening {
println!("Good evening!");
}
}
In the code comments it's clear that we are looking at Booleans which are a type that is either true
or false
. With that in mind, let's take a look at what the errors are to make sure we have a complete picture.
primitive_trype1.rs
errors
⚠️ Compiling of exercises/primitive_types/primitive_types1.rs failed! Please try again. Here's the output:
error: expected identifier, found keyword `if`
--> exercises/primitive_types/primitive_types1.rs:16:5
|
16 | if is_evening {
| ^^ expected identifier, found keyword
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `is_evening`
--> exercises/primitive_types/primitive_types1.rs:16:8
|
16 | if is_evening {
| ^^^^^^^^^^ expected one of `:`, `;`, `=`, `@`, or `|`
error: aborting due to 2 previous errors
These errors point to the fact that the if_evening
portion of the code is incomplete, in fact it's almost like the compiler is saying "wait a minute, shouldn't you let me know what is_evening
is?" instead, it found the keyword if
.
primitive_types1.rs
solution
// primitive_types1.rs
// Fill in the rest of the line that has code missing!
// No hints, there's no tricks, just get used to typing these :)
// I AM NOT DONE
fn main() {
// Booleans (`bool`)
let is_morning = true;
if is_morning {
println!("Good morning!");
}
let is_evening = false; // easy enough to complete this as above
if is_evening {
println!("Good evening!");
}
}
This works out pretty quickly, by just defining what is_evening
is with let is_evening = false;
we get the code to compile and it prints:
🎉 🎉 The code is compiling! 🎉 🎉
Output:
====================
Good morning!
====================
Great, but what would happen if we make the both of them true
? Let's find out.
fn main() {
// Booleans (`bool`)
let is_morning = true;
if is_morning {
println!("Good morning!");
}
let is_evening = true; // making both `true`
if is_evening {
println!("Good evening!");
}
}
This time we get a slightly different print, but the code still compiles.
🎉 🎉 The code is compiling! 🎉 🎉
Output:
====================
Good morning!
Good evening!
====================
Simple enough, we're on to the next one.
primitive_types2.rs
// primitive_types2.rs
// Fill in the rest of the line that has code missing!
// No hints, there's no tricks, just get used to typing these :)
// I AM NOT DONE
fn main() {
// Characters (`char`)
// Note the _single_ quotes, these are different from the double quotes
// you've been seeing around.
let my_first_initial = 'C';
if my_first_initial.is_alphabetic() {
println!("Alphabetical!");
} else if my_first_initial.is_numeric() {
println!("Numerical!");
} else {
println!("Neither alphabetic nor numeric!");
}
let // Finish this line like the example! What's your favorite character?
// Try a letter, try a number, try a special character, try a character
// from a different language than your own, try an emoji!
if your_character.is_alphabetic() {
println!("Alphabetical!");
} else if your_character.is_numeric() {
println!("Numerical!");
} else {
println!("Neither alphabetic nor numeric!");
}
}
Again we have no hints, so we have pay close attention to the code and the errors we get from the Rust compiler.
⚠️ Compiling of exercises/primitive_types/primitive_types2.rs failed! Please try again. Here's the output:
error: expected identifier, found keyword `if`
--> exercises/primitive_types/primitive_types2.rs:24:5
|
24 | if your_character.is_alphabetic() {
| ^^ expected identifier, found keyword
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `your_character`
--> exercises/primitive_types/primitive_types2.rs:24:8
|
24 | if your_character.is_alphabetic() {
| ^^^^^^^^^^^^^^ expected one of `:`, `;`, `=`, `@`, or `|`
error: aborting due to 2 previous errors
This looks similar to what we got in our previous exercise, essentially telling us that the your_character
part of the code is incomplete.
Let's go through the comments in the code.
- The first comment in
fn main()
tells us that we are looking at Characters - Second comment makes sure that we notice the use of single quotes on the line
let my_first_intial = 'C'
- The third comment tells us to finish the
let
statement using the example we've seen but use our favorite character.
Looking at how the rest of the code is written, to make it easier on us, we can use the your_character
variable that is being used, but of course as the errors tells us, is undefined. Let's define it.
fn main() {
let my_first_initial = 'C';
if my_first_initial.is_alphabetic() {
println!("Alphabetical!");
} else if my_first_initial.is_numeric() {
println!("Numerical!");
} else {
println!("Neither alphabetic nor numeric!");
}
let your_character = '🦀'; // we define it as a crab emoji just for fun.
if your_character.is_alphabetic() {
println!("Alphabetical!");
} else if your_character.is_numeric() {
println!("Numerical!");
} else {
println!("Neither alphabetic nor numeric!");
}
}
primitive_types3.rs
// primitive_types3.rs
// Create an array with at least 100 elements in it where the ??? is.
// Execute `rustlings hint primitive_types3` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
fn main() {
let a = ???
if a.len() >= 100 {
println!("Wow, that's a big array!");
} else {
println!("Meh, I eat arrays like that for breakfast.");
}
}
Here we have clear instructions on what we need to do, and we even have a hint if we need it. But let's look at the errors first:
⚠️ Compiling of exercises/primitive_types/primitive_types3.rs failed! Please try again. Here's the output:
error: expected expression, found `?`
--> exercises/primitive_types/primitive_types3.rs:8:13
|
8 | let a = ???
| ^ expected expression
error: aborting due to previous error
Short and sweet, we see that on line 8, there's an expected expression where we need to replace the ???
question marks. So what kind of expression do we need, well the instructions tell us it should be an array with at least 100 elements in it.
Array Review
Let's quickly review the ways that we can create an array in Rust.
One of the simplest ways we can create an array in Rust is by using the []
square brackets and listing the elements inside of it, like this:
let a = [1, 2, 3, 4, 5, 6];
We can also define the array's type by using another set of square brackets before the definition of the array, in a similar what that you define types when defining variables.
let a: [i32; 6] = [1, 2, 3, 4, 5, 6];
These are both valid, but remember in our exercise we have to make an array with at least 100 elements in it -- there must be a better way. Luckily there is, as long as we want the array to contain the same value we can initialize the array like this:
let a = [3;5];
This will give us an array called a
with that will contain 5
elements with their value set to 3
this is the same as writing
let a = [3, 3, 3, 3, 3];
but clearly in a more concise way.
primitive_types3.rs
Solution
Now that we have this information fresh in our minds we can clearly see the winning solution for our problem of having 100 elements in an array. Let's do it.
fn main() {
let a = [1; 100];
if a.len() >= 100 {
println!("Wow, that is a big array!");
} else {
println!("Meh, I eat arrays like that for breakfast.");
}
}
We get this back from the compiler:
Output:
====================
Wow, that is a big array!
====================
and just to confirm, what if we make the array less than 100 elements? Let's just change the 100
to 99
like this: let a = [1; 99];
Output:
====================
Meh, I eat arrays like that for breakfast.
====================
primitive_types4.rs
// primitive_types4.rs
// Get a slice out of Array a where the ??? is so that the test passes.
// Execute `rustlings hint primitive_types4` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
#[test]
fn slice_out_of_array() {
let a = [1, 2, 3, 4, 5];
let nice_slice = ???
assert_eq!([2, 3, 4], nice_slice)
}
primitive_types4.rs
error
⚠️ Compiling of exercises/primitive_types/primitive_types4.rs failed! Please try again. Here's the output:
error: expected expression, found `?`
--> exercises/primitive_types/primitive_types4.rs:11:22
|
11 | let nice_slice = ???
| ^ expected expression
error: aborting due to previous error
In this piece of code we see almost the exact same set-up having to define a variable, in this case we need to define it with a slice. Remembering a slice is essentially how we refer to part of an array, remember when we had the 100 element array in the previous exercise, or even a bigger array that had thousands of elements. Well what if only needed to access part of the array? We would use a slice in this scenario so let's do it.
We define a slice by using &[ ]
the &
makes it like a reference, so we don't have ownership of the array, but we can go deeper into this another time, let's just define this slice.
The error code is also very straightforward, we're being told that we're missing an expression.
primitive_types4.rs
solution
we get a hint by the assert_eq!
part of the code as to what it's looking for, elements 2
, 3
, and 4
so that's what we'll do.
fn slice_out_of_array() {
let a = [1, 2, 3, 4, 5];
let nice_slice = &a[1..4]; // using `a&[]` to create a slice we use the `..` to define the range
assert_eq!([2, 3, 4], nice_slice)
}
So in this case we define the range to to be between 1 and 4
but remember that the first element in the array is at index 0
and element 4
is index 5
. Rust excludes the final element and therefore we get numbers 2, 3, 4
which correspond to index 1, 2, 3
.
All we get on this one is that the test is passing and code is compiling.
🎉 🎉 The code is compiling, and the tests pass! 🎉 🎉
Just to confirm what we're talking about above, let's use a different slice range that what know is the solution, let's use &a[0..5]
and see what happens.
let nice_slice = &a[0..5];
Test Failed
running 1 test
test slice_out_of_array ... FAILED
successes:
successes:
failures:
---- slice_out_of_array stdout ----
thread 'slice_out_of_array' panicked at 'assertion failed: `(left == right)`
left: `[2, 3, 4]`,
right: `[1, 2, 3, 4, 5]`', exercises/primitive_types/primitive_types4.rs:13:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
slice_out_of_array
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
As expected the test fails, and we see the elements that we select by using the &a[0..5]
makes the test panic because the assertion failed: (left == right)
in our code the left doesn't equal the right and we can see that we are accessing the elements starting at index 0
and ending at index 5
.
primitive_types5.rs
// primitive_types5.rs
// Destructure the `cat` tuple so that the println will work.
// Execute `rustlings hint primitive_types5` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
fn main() {
let cat = ("Furry McFurson", 3.5);
let /* your pattern here */ = cat;
println!("{} is {} years old.", name, age);
}
primitive_types5.rs
error
⚠️ Compiling of exercises/primitive_types/primitive_types5.rs failed! Please try again. Here's the output:
error: expected pattern, found `=`
--> exercises/primitive_types/primitive_types5.rs:9:33
|
9 | let /* your pattern here */ = cat;
| ^ expected pattern
error: aborting due to previous error
Our instructions are to destructure the cat
tuple so that the println
will work, seems simple enough we have a clear indication in the code where this should take place, in our let
variable assignment on line 8.
The Tuple Type
So let's quickly recap a Tuple and how we destructure it. A tuple is a compound type meaning that it can group together elements of different types, for example in our let cat = ("Furry McFurson", 3.5)
we can see that we have a &str and a floating-point type.
Let's keep things simple for now and not go too deep into the &str
and what it means, for now we know it represents a string in our code.
So, another way we could have defined this tuple to be more explicit would have been like so (similar to our array in a previous exercise, where we defined the type for an array):
let cat: (&str, f64) = ("Furry McFurson", 3.5);
When we bind tuple to a variable, like in this case cat
the variable is bound to the entire tuple as it's considered a single compound element. So to get a single element out of the tuple we have to destructure the tuple by sort of inverting the variable like this:
let (a, b) = variable
primitive_types5.rs
solution
In our case we can see that in the println!
statement we are looking for a name
and age
elements, so let's plug these into our code.
fn main() {
let cat = ("Furry McFurson", 3.5);
let (name, age) = cat;
println!("{} is {} years old.", name, age);
}
Let's check our output
Output:
====================
Furry McFurson is 3.5 years old.
====================
primitive_types6.rs
// primitive_types6.rs
// Use a tuple index to access the second element of `numbers`.
// You can put the expression for the second element where ??? is so that the test passes.
// Execute `rustlings hint primitive_types6` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
#[test]
fn indexing_tuple() {
let numbers = (1, 2, 3);
// Replace below ??? with the tuple indexing syntax.
let second = ???;
assert_eq!(2, second,
"This is not the 2nd number in the tuple!")
}
primitive_types6.rs
error
⚠️ Compiling of exercises/primitive_types/primitive_types6.rs failed! Please try again. Here's the output:
error: expected expression, found `?`
--> exercises/primitive_types/primitive_types6.rs:12:18
|
12 | let second = ???;
| ^ expected expression
error: aborting due to previous error
Our instructions say to use a tuple index to access the second element of numbers
and we can use place the expression in line 12 where the let second = ???
, simple enough.
Tuple Indexing
But how do we access a tuple directly? By using the variable a period .
followed by the index value.
let indexing = variable.0
Alright then, let's apply this to our problem.
primitive_types6.rs
solution
#[test]
fn indexing_tuple() {
let numbers = (1, 2, 3);
let second = numbers.1; // using the tuple indexing syntax to get the 2nd element which is at index `1`
assert_eq!(2, second, "This is not the 2nd number in the tuple!")
}
The only tricky part is to remember that indexes start at 0
so the second element is at index 1
. So if we were for example to change the number.1
to number.2
, if we mistakenly thought the correct index was 2
we'd get this text in our test:
running 1 test
test indexing_tuple ... FAILED
successes:
successes:
failures:
---- indexing_tuple stdout ----
thread 'indexing_tuple' panicked at 'assertion failed: `(left == right)`
left: `2`,
right: `3`: This is not the 2nd number in the tuple!', exercises/primitive_types/primitive_types6.rs:14:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
indexing_tuple
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
With the correct index number we don't get anything special but a celebratory code is compiling
message.
Conclusion
In this post, we tackled various exercises related to primitive types in Rust. We explored arrays, tuples, slices, and tuple indexing while understanding how to create and manipulate them. We also learned about the error messages provided by the Rust compiler and how to interpret and resolve them to make our code work as expected.
These exercises are essential for building a strong foundation in Rust, as primitive types are the building blocks for more complex data structures and programs. By mastering these concepts, you'll be well-prepared to tackle more advanced Rust topics and further enhance your Rust programming skills.
Keep practicing and exploring the Rust language, and don't forget to consult the official Rust documentation when in doubt!