add a note to the README about this being a tutorial for an ancient version of Rust
[rust-101.git] / src / part03.rs
index 3dfb2abbf4c7c8da811a513d144ccc7920341410..b81bbc371cd7c3a8c2dc3d16de6c83a58d08a319 100644 (file)
@@ -30,7 +30,7 @@ fn read_vec() -> Vec<i32> {
     //@ concurrently, that also reads from standard input? The result would be a mess. Hence
     //@ Rust requires us to `lock` standard input if we want to perform large operations on
     //@ it. (See [the documentation](https://doc.rust-lang.org/stable/std/io/struct.Stdin.html) for
     //@ concurrently, that also reads from standard input? The result would be a mess. Hence
     //@ Rust requires us to `lock` standard input if we want to perform large operations on
     //@ it. (See [the documentation](https://doc.rust-lang.org/stable/std/io/struct.Stdin.html) for
-    //@ more details.) 
+    //@ more details.)
     for line in stdin.lock().lines() {
         // Rust's type for (dynamic, growable) strings is `String`. However, our variable `line`
         // here is not yet of that type: It has type `io::Result<String>`.
     for line in stdin.lock().lines() {
         // Rust's type for (dynamic, growable) strings is `String`. However, our variable `line`
         // here is not yet of that type: It has type `io::Result<String>`.
@@ -60,7 +60,6 @@ fn read_vec() -> Vec<i32> {
         //@ the return type of the function), but that's a bit too much magic for my taste. We are
         //@ being more explicit here: `parse::<i32>` is `parse` with its generic type set to `i32`.
         match line.trim().parse::<i32>() {
         //@ the return type of the function), but that's a bit too much magic for my taste. We are
         //@ being more explicit here: `parse::<i32>` is `parse` with its generic type set to `i32`.
         match line.trim().parse::<i32>() {
-
             //@ `parse` returns again a `Result`, and this time we use a `match` to handle errors
             //@ (like, the user entering something that is not a number).
             //@ This is a common pattern in Rust: Operations that could go wrong will return
             //@ `parse` returns again a `Result`, and this time we use a `match` to handle errors
             //@ (like, the user entering something that is not a number).
             //@ This is a common pattern in Rust: Operations that could go wrong will return
@@ -100,9 +99,10 @@ pub fn main() {
     min.print();                                                    /*@*/
 }
 
     min.print();                                                    /*@*/
 }
 
-// **Exercise 03.1**: Define a trait `Print` to write a generic version of
-// `SomethingOrNothing::print`.
-// Implement that trait for `i32`, and change the code above to use it.
+// **Exercise 03.1**: The goal is to write a generic version of `SomethingOrNothing::print`.
+// To this end, define a trait `Print` that provides (simple) generic printing, and implement
+// that trait for `i32`. Then define `SomethingOrNothing::print2` to use that trait, and change
+// `main` above to use the new generic `print2` function.
 // I will again provide a skeleton for this solution. It also shows how to attach bounds to generic
 // implementations (just compare it to the `impl` block from the previous exercise).
 // You can read this as "For all types `T` satisfying the `Print` trait, I provide an implementation
 // I will again provide a skeleton for this solution. It also shows how to attach bounds to generic
 // implementations (just compare it to the `impl` block from the previous exercise).
 // You can read this as "For all types `T` satisfying the `Print` trait, I provide an implementation
@@ -115,6 +115,9 @@ pub fn main() {
 pub trait Print {
     /* Add things here */
 }
 pub trait Print {
     /* Add things here */
 }
+impl Print for i32 {
+    /* Add things here */
+}
 impl<T: Print> SomethingOrNothing<T> {
     fn print2(self) {
         unimplemented!()
 impl<T: Print> SomethingOrNothing<T> {
     fn print2(self) {
         unimplemented!()