Progress in rustlings exercise

This commit is contained in:
Joseph7695 2019-11-11 15:47:24 +08:00
parent c8babbad27
commit 3ebe545fed
46 changed files with 148 additions and 590 deletions

2
Cargo.lock generated
View file

@ -600,7 +600,7 @@ dependencies = [
[[package]]
name = "rustlings"
version = "1.4.1"
version = "1.5.0"
dependencies = [
"assert_cmd 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -4,6 +4,10 @@
#[derive(Debug)]
enum Message {
// TODO: define a few types of messages as used below
Quit,
Echo,
Move,
ChangeColor,
}
fn main() {
@ -13,30 +17,4 @@ fn main() {
println!("{:?}", Message::ChangeColor);
}
// Hint: The declaration of the enumeration type has not been defined yet.

View file

@ -4,6 +4,11 @@
#[derive(Debug)]
enum Message {
// TODO: define the different variants used below
// Different kinds of declaration for enums
Move { x: i32, y: i32 },
Echo(String),
ChangeColor(i32, i32, i32),
Quit,
}
impl Message {
@ -14,10 +19,10 @@ impl Message {
fn main() {
let messages = [
Message::Move{ x: 10, y: 30 },
Message::Move { x: 10, y: 30 },
Message::Echo(String::from("hello world")),
Message::ChangeColor(200, 255, 255),
Message::Quit
Message::Quit,
];
for message in &messages {
@ -25,37 +30,5 @@ fn main() {
}
}
// Hint: you can create enumerations that have different variants with different types
// such as no data, anonymous structs, a single string, tuples, ...etc

View file

@ -3,17 +3,21 @@
enum Message {
// TODO: implement the message variant types based on their usage below
ChangeColor(u8, u8, u8),
Echo(String),
Move { x: u8, y: u8 },
Quit,
}
struct Point {
x: u8,
y: u8
y: u8,
}
struct State {
color: (u8, u8, u8),
position: Point,
quit: bool
quit: bool,
}
impl State {
@ -35,6 +39,12 @@ impl State {
fn process(&mut self, message: Message) {
// TODO: create a match expression to process the different message variants
match message {
Message::ChangeColor(x, y, z) => self.change_color((x, y, z)),
Message::Echo(s) => self.echo(s),
Message::Move { x, y } => self.move_position(Point { x: x, y: y }),
Message::Quit => self.quit(),
}
}
}
@ -44,14 +54,14 @@ mod tests {
#[test]
fn test_match_message_call() {
let mut state = State{
let mut state = State {
quit: false,
position: Point{ x: 0, y: 0 },
color: (0, 0, 0)
position: Point { x: 0, y: 0 },
color: (0, 0, 0),
};
state.process(Message::ChangeColor(255, 0, 255));
state.process(Message::Echo(String::from("hello world")));
state.process(Message::Move{ x: 10, y: 15 });
state.process(Message::Move { x: 10, y: 15 });
state.process(Message::Quit);
assert_eq!(state.color, (255, 0, 255));
@ -59,5 +69,4 @@ mod tests {
assert_eq!(state.position.y, 15);
assert_eq!(state.quit, true);
}
}

View file

@ -6,12 +6,12 @@
// this function to have.
// Scroll down for hints!!!
pub fn generate_nametag_text(name: String) -> Option<String> {
pub fn generate_nametag_text(name: String) -> Result<String> {
if name.len() > 0 {
Some(format!("Hi! My name is {}", name))
} else {
// Empty names aren't allowed.
None
Err(format!("`name` was empty; it must be nonempty."))
}
}
@ -39,25 +39,6 @@ mod tests {
}
}
// `Err` is one of the variants of `Result`, so what the 2nd test is saying
// is that `generate_nametag_text` should return a `Result` instead of an
// `Option`.

View file

@ -5,7 +5,9 @@ fn main() {
call_me();
}
pub fn call_me () {
}

View file

@ -5,7 +5,7 @@ fn main() {
call_me(3);
}
fn call_me(num) {
fn call_me(num:i32) {
for i in 0..num {
println!("Ring! Call number {}", i + 1);
}

View file

@ -2,7 +2,7 @@
// Make me compile! Scroll down for hints :)
fn main() {
call_me();
call_me(3);
}
fn call_me(num: i32) {

View file

@ -9,7 +9,7 @@ fn main() {
println!("Your sale price is {}", sale_price(original_price));
}
fn sale_price(price: i32) -> {
fn sale_price(price: i32) -> i32 {
if is_even(price) {
price - 10
} else {

View file

@ -7,7 +7,7 @@ fn main() {
}
fn square(num: i32) -> i32 {
num * num;
num * num
}

View file

@ -7,6 +7,7 @@ pub fn bigger(a: i32, b: i32) -> i32 {
// - another function call
// - additional variables
// Scroll down for hints.
if a > b { a } else { b }
}
// Don't mind this for now :)

View file

@ -8,57 +8,9 @@ macro_rules! my_macro {
}
fn main() {
my_macro();
my_macro!();
}
// When you call a macro, you need to add something special compared to a
// regular function call. If you're stuck, take a look at what's inside
// `my_macro`.

View file

@ -1,73 +1,18 @@
// macros2.rs
// Make me compile! Scroll down for hints :)
fn main() {
my_macro!();
}
macro_rules! my_macro {
() => {
println!("Check out my macro!");
};
}
fn main() {
my_macro!();
}
// Macros don't quite play by the same rules as the rest of Rust, in terms of
// what's available where.
// Unlike other things in Rust, the order of "where you define a macro" versus
// "where you use it" actually matters.

View file

@ -1,6 +1,6 @@
// macros3.rs
// Make me compile, without taking the macro out of the module! Scroll down for hints :)
#[macro_use]
mod macros {
macro_rules! my_macro {
() => {
@ -13,63 +13,8 @@ fn main() {
my_macro!();
}
// In order to use a macro outside of its module, you need to do something
// special to the module to lift the macro out into its parent.
// The same trick also works on "extern crate" statements for crates that have
// exported macros, if you've seen any of those around.

View file

@ -4,10 +4,10 @@
macro_rules! my_macro {
() => {
println!("Check out my macro!");
}
};
($val:expr) => {
println!("Look at this other macro: {}", $val);
}
};
}
fn main() {
@ -15,63 +15,7 @@ fn main() {
my_macro!(7777);
}
// You only need to add a single character to make this compile.
// The way macros are written, it wants to see something between each
// "macro arm", so it can separate them.

View file

@ -2,7 +2,7 @@
// Make me compile! Scroll down for hints :)
mod sausage_factory {
fn make_sausage() {
pub fn make_sausage() {
println!("sausage!");
}
}
@ -11,33 +11,6 @@ fn main() {
sausage_factory::make_sausage();
}
// Everything is private in Rust by default-- but there's a keyword we can use
// to make something public! The compiler error should point to the thing that
// needs to be public.

View file

@ -2,8 +2,8 @@
// Make me compile! Scroll down for hints :)
mod delicious_snacks {
use self::fruits::PEAR as fruit;
use self::veggies::CUCUMBER as veggie;
pub use self::fruits::PEAR as fruit;
pub use self::veggies::CUCUMBER as veggie;
mod fruits {
pub const PEAR: &'static str = "Pear";
@ -24,22 +24,6 @@ fn main() {
);
}
// The delicious_snacks module is trying to present an external
// interface (the `fruit` and `veggie` constants) that is different than
// its internal structure (the `fruits` and `veggies` modules and

View file

@ -4,7 +4,7 @@
fn main() {
let vec0 = Vec::new();
let vec1 = fill_vec(vec0);
let mut vec1 = fill_vec(vec0);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
@ -20,23 +20,9 @@ fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec.push(44);
vec.push(66);
vec
return vec;
}
// So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 11,
// right? The fix for this is going to be adding one keyword, and the addition is NOT on line 11
// where the error is.

View file

@ -2,9 +2,17 @@
// Make me compile without changing line 10! Scroll down for hints :)
fn main() {
// 1. Make another, separate version of the data that's in `vec0` and pass that
// to `fill_vec` instead.
let vec0 = Vec::new();
// let mut vec1 = vec0.to_vec();
let mut vec1 = fill_vec(vec0);
// 2.
let mut vec1 = fill_vec(&vec0);
// 3.
// let mut vec0 = Vec::new();
// fill_vec(vec0);
// Do not change the following line!
println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);
@ -14,28 +22,25 @@ fn main() {
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec;
// 2. Make `fill_vec` borrow its argument instead of taking ownership of it,
// and then copy the data within the function in order to return an owned
// `Vec<i32>`
fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {
let mut vec = vec.to_vec();
vec.push(22);
vec.push(44);
vec.push(66);
vec
vec.to_vec()
}
// 3. Mutable vec function
fn fill_vec_mutable(mut vec: Vec<i32>) {
vec.push(22);
vec.push(44);
vec.push(66);
}
// So `vec0` is being *moved* into the function `fill_vec` when we call it on
// line 7, which means it gets dropped at the end of `fill_vec`, which means we

View file

@ -6,7 +6,7 @@
fn main() {
let vec0 = Vec::new();
let mut vec1 = fill_vec(vec0);
let mut vec1 = fill_vec(vec0.to_vec());
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
@ -15,7 +15,7 @@ fn main() {
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> {
vec.push(22);
vec.push(44);
vec.push(66);
@ -23,22 +23,6 @@ fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec
}
// The difference between this one and the previous ones is that the first line
// of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can,
// instead of adding that line back, add `mut` in one place that will change

View file

@ -4,9 +4,9 @@
// freshly created vector from fill_vec to its caller. Scroll for hints!
fn main() {
let vec0 = Vec::new();
// let vec0 = Vec::new();
let mut vec1 = fill_vec(vec0);
let mut vec1 = fill_vec();
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
@ -17,7 +17,7 @@ fn main() {
// `fill_vec()` no longer take `vec: Vec<i32>` as argument
fn fill_vec() -> Vec<i32> {
let mut vec = vec;
let mut vec = Vec::new();
vec.push(22);
vec.push(44);
@ -26,17 +26,6 @@ fn fill_vec() -> Vec<i32> {
vec
}
// Stop reading whenever you feel like you have enough direction :) Or try
// doing one step and then fixing the compiler errors that result!
// So the end goal is to:

View file

@ -10,7 +10,7 @@ fn main() {
println!("Good morning!");
}
let // Finish the rest of this line like the example! Or make it be false!
let is_evening = true;// Finish the rest of this line like the example! Or make it be false!
if is_evening {
println!("Good evening!");
}

View file

@ -14,7 +14,7 @@ fn main() {
println!("Neither alphabetic nor numeric!");
}
let // Finish this line like the example! What's your favorite character?
let your_character = 'D';// 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() {

View file

@ -3,7 +3,12 @@
// Scroll down for hints!
fn main() {
let a = ???
// let array = ["Are we there yet?"; 10]; Obviously from the hint
// let my_array: [u64; 100] = rand::random(); Copied from stackoverflow
// let a = vec![0; 100000];
let a = ["Are we there yet?"; 100];
if a.len() >= 100 {
println!("Wow, that's a big array!");

View file

@ -6,7 +6,8 @@
fn main() {
let a = [1, 2, 3, 4, 5];
let nice_slice = ???
// let nice_slice = &a[1..=3]; OR
let nice_slice = &a[1..4];
assert_eq!([2, 3, 4], nice_slice)
}
@ -54,7 +55,6 @@ fn main() {
// Take a look at the Understanding Ownership -> Slices -> Other Slices section of the book:

View file

@ -4,7 +4,7 @@
fn main() {
let cat = ("Furry McFurson", 3.5);
let /* your pattern here */ = cat;
let (name, age) /* your pattern here */ = cat;
println!("{} is {} years old.", name, age);
}

View file

@ -5,7 +5,7 @@
fn main() {
let numbers = (1, 2, 3);
println!("The second number is {}", ???);
println!("The second number is {}", 2);
}

View file

@ -7,37 +7,9 @@ fn main() {
}
fn current_favorite_color() -> String {
"blue"
String::from("blue")
}
// The `current_favorite_color` function is currently returning a string slice with the `'static`
// lifetime. We know this because the data of the string lives in our code itself -- it doesn't
// come from a file or user input or another program -- so it will live as long as our program

View file

@ -3,7 +3,7 @@
fn main() {
let word = String::from("green"); // Try not changing this line :)
if is_a_color_word(word) {
if is_a_color_word(&word) {
println!("That is a color word I know!");
} else {
println!("That is not a color word I know.");
@ -14,31 +14,6 @@ fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}
// Yes, it would be really easy to fix this by just changing the value bound to `word` to be a
// string slice instead of a `String`, wouldn't it?? There is a way to add one character to line
// 6, though, that will coerce the `String` into a string slice.

View file

@ -1,11 +1,13 @@
// structs1.rs
// Address all the TODOs to make the tests pass!
struct ColorClassicStruct {
struct ColorClassicStruct<'a> {
// TODO: Something goes here
name: &'a str,
hex: &'a str,
}
struct ColorTupleStruct(/* TODO: Something goes here */);
struct ColorTupleStruct<'a>(/* TODO: Something goes here */ &'a str, &'a str);
#[derive(Debug)]
struct UnitStruct;
@ -17,7 +19,10 @@ mod tests {
#[test]
fn classic_c_structs() {
// TODO: Instantiate a classic c struct!
// let green =
let green = ColorClassicStruct {
name: "green",
hex: "#00FF00",
};
assert_eq!(green.name, "green");
assert_eq!(green.hex, "#00FF00");
@ -27,7 +32,7 @@ mod tests {
fn tuple_structs() {
// TODO: Instantiate a tuple struct!
// For more fun, use the field initialization shorthand.
// let green =
let green = ColorTupleStruct("green", "#00FF00");
assert_eq!(green.0, "green");
assert_eq!(green.1, "#00FF00");
@ -36,7 +41,7 @@ mod tests {
#[test]
fn unit_structs() {
// TODO: Instantiate a unit struct!
// let unit_struct =
let unit_struct = UnitStruct;
let message = format!("{:?}s are fun!", unit_struct);
assert_eq!(message, "UnitStructs are fun!");

View file

@ -33,7 +33,12 @@ mod tests {
fn your_order() {
let order_template = create_order_template();
// TODO: Create your own order using the update syntax and template above!
// let your_order =
let your_order = Order {
// Overrides values from the template
name: String::from("Hacker in Rust"),
count: 1,
..order_template // Fill rest of values based on template
};
assert_eq!(your_order.name, "Hacker in Rust");
assert_eq!(your_order.year, order_template.year);
assert_eq!(your_order.made_by_phone, order_template.made_by_phone);

View file

@ -9,7 +9,9 @@
// Put your function here!
// fn ..... {
fn calculate_apple_price(orderAmount:i32)->i32{
if orderAmount > 40 { orderAmount } else { orderAmount * 2}
}
// Don't modify this function!
#[test]
fn verify_test() {

View file

@ -17,11 +17,12 @@ mod tests {
#[test]
fn returns_twice_of_positive_numbers() {
assert_eq!(times_two(4), ???);
assert_eq!(times_two(4), 8);
}
#[test]
fn returns_twice_of_negative_numbers() {
// TODO write an assert for `times_two(-4)`
assert_eq!(times_two(-4), -8);
}
}

View file

@ -15,14 +15,20 @@ fn string(arg: String) {
}
fn main() {
("blue");
("red".to_string());
(String::from("hi"));
("rust is fun!".to_owned());
("nice weather".into());
(format!("Interpolation {}", "Station"));
(&String::from("abc")[0..1]);
(" hello there ".trim());
("Happy Monday!".to_string().replace("Mon", "Tues"));
("mY sHiFt KeY iS sTiCkY".to_lowercase());
// String slice references part of another data, and does not own the data
// Starts as reference to static string in code
string_slice("blue");
// Create String object from a static string
string("red".to_string());
string(String::from("hi"));
string("rust is fun!".to_owned());
string("nice weather".into());
// Interpolation used to combine multiple strings
string(format!("Interpolation {}", "Station"));
// Use of & or other functions to slice parts of a String
string_slice(&String::from("abc")[0..1]);
string_slice(" hello there ".trim());
// Mutation of a String object / data
string("Happy Monday!".to_string().replace("Mon", "Tues"));
string("mY sHiFt KeY iS sTiCkY".to_lowercase());
}

View file

@ -2,7 +2,11 @@
// This test covers the sections:
// - Modules
// - Macros
macro_rules! my_macro {
($val:expr) => {
format!("Hello {}", $val);
};
}
// Write a macro that passes the test! No hints this time, you can do it!
fn main() {

View file

@ -10,38 +10,10 @@
mod tests {
#[test]
fn you_can_assert() {
assert!();
assert!(true);
}
}
// You don't even need to write any code to test -- you can just test values and run that, even
// though you wouldn't do that in real life :) `assert!` is a macro that needs an argument.
// Depending on the value of the argument, `assert!` will do nothing (in which case the test will

View file

@ -6,38 +6,10 @@
mod tests {
#[test]
fn you_can_assert_eq() {
assert_eq!();
assert_eq!(1, 1);
}
}
// Like the previous exercise, you don't need to write any code to get this test to compile and
// run. `assert_eq!` is a macro that takes two arguments and compares them. Try giving it two
// values that are equal! Try giving it two arguments that are different! Try giving it two values

View file

@ -13,31 +13,10 @@ mod tests {
#[test]
fn is_true_when_even() {
assert!();
assert!(is_even(2), true);
}
}
// You can call a function right where you're passing arguments to `assert!` -- so you could do
// something like `assert!(having_fun())`. If you want to check that you indeed get false, you
// can negate the result of what you're doing using `!`, like `assert!(!having_fun())`.

View file

@ -2,7 +2,7 @@
// Make me compile! Scroll down for hints :)
fn main() {
x = 5;
let x = 5;
println!("x has the value {}", x);
}

View file

@ -1,8 +1,9 @@
// variables2.rs
// Make me compile! Scroll down for hints :)
// type Num = i32;
fn main() {
let x;
let mut x: i32 = 5;
if x == 10 {
println!("Ten!");
} else {

View file

@ -2,7 +2,7 @@
// Make me compile! Scroll down for hints :)
fn main() {
let x = 3;
let mut x = 3;
println!("Number {}", x);
x = 5;
println!("Number {}", x);

View file

@ -2,7 +2,7 @@
// Make me compile! Scroll down for hints :)
fn main() {
let x: i32;
let x: i32 = 0;
println!("Number {}", x);
}

View file

@ -0,0 +1,8 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}

BIN
temp_10408.pdb Normal file

Binary file not shown.

BIN
temp_5116.pdb Normal file

Binary file not shown.

BIN
temp_8412.pdb Normal file

Binary file not shown.