avoid using std::cmp::min, for it doesn't support f32...
authorRalf Jung <post@ralfj.de>
Tue, 23 Jun 2015 15:27:36 +0000 (17:27 +0200)
committerRalf Jung <post@ralfj.de>
Tue, 23 Jun 2015 15:27:36 +0000 (17:27 +0200)
solutions/src/lib.rs
src/part00.rs
src/part01.rs
src/part02.rs
src/part03.rs
src/part04.rs

index aff442c18d5938354be9fe361f7eddcabdf51439..cbe97058cba21e0308fff616e385c8d37da53f90 100644 (file)
@@ -1,2 +1,2 @@
 pub mod bigint;
 pub mod bigint;
-pub mod vec_min;
+pub mod vec;
index 4deb82946709e1b5944e9076e4c3db69bd52b98f..1648ba177295beec84ba5f711ab775577ed7bad8 100644 (file)
@@ -4,9 +4,6 @@
 // As our first piece of Rust code, we want to write a function that computes the
 // minimum of a list.
 
 // As our first piece of Rust code, we want to write a function that computes the
 // minimum of a list.
 
-// We are going to make use of the standard library, so let's import that:
-use std;
-
 // ## Getting started
 // Let us start by thinking about the *type* of our function. Rust forces us to give the types of
 // all arguments, and the return type, before we even start writing the body. In the case of our minimum
 // ## Getting started
 // Let us start by thinking about the *type* of our function. Rust forces us to give the types of
 // all arguments, and the return type, before we even start writing the body. In the case of our minimum
@@ -48,9 +45,10 @@ fn vec_min(vec: Vec<i32>) -> NumberOrNothing {
             NumberOrNothing::Nothing => {
                 min = NumberOrNothing::Number(el);
             },
             NumberOrNothing::Nothing => {
                 min = NumberOrNothing::Number(el);
             },
-            // In this arm, `min` is currently the number `n`, so let's compute the new minimum and store it.
+            // In this arm, `min` is currently the number `n`, so let's compute the new minimum and store it. We will write
+            // the function `min_i32` just after we completed this one.
             NumberOrNothing::Number(n) => {
             NumberOrNothing::Number(n) => {
-                let new_min = std::cmp::min(n, el);
+                let new_min = min_i32(n, el);
                 min = NumberOrNothing::Number(new_min);
             }
         }
                 min = NumberOrNothing::Number(new_min);
             }
         }
@@ -59,6 +57,15 @@ fn vec_min(vec: Vec<i32>) -> NumberOrNothing {
     return min;
 }
 
     return min;
 }
 
+// Now that we reduced the problem to computing the minimum of two integers, let's do that.
+fn min_i32(a: i32, b: i32) -> i32 {
+    if a < b {
+        return a;
+    } else {
+        return b;
+    }
+}
+
 // Phew. We wrote our first Rust function! But all this `NumberOrNothing::` is getting kind of
 // ugly. Can't we do that nicer?
 
 // Phew. We wrote our first Rust function! But all this `NumberOrNothing::` is getting kind of
 // ugly. Can't we do that nicer?
 
index 05696a50f98f17678e3b9922acc3a17157d9c6ce..bb3e919f980bc3e4794c2c3a8942aaa31985d08f 100644 (file)
@@ -1,8 +1,6 @@
 // Rust-101, Part 01: Expressions, Inherent methods
 // ================================================
 
 // Rust-101, Part 01: Expressions, Inherent methods
 // ================================================
 
-use std;
-
 // Even though our code from the first part works, we can still learn a
 // lot by making it prettier. To understand how, it is important to
 // understand that Rust is an "expression-based" language. This means that most of the
 // Even though our code from the first part works, we can still learn a
 // lot by making it prettier. To understand how, it is important to
 // understand that Rust is an "expression-based" language. This means that most of the
@@ -35,8 +33,15 @@ fn number_or_default(n: NumberOrNothing, default: i32) -> i32 {
     }
 }
 
     }
 }
 
-// With this fresh knowledge, let us now refactor `vec_min`.
+// Let us now refactor `vec_min`.
 fn vec_min(v: Vec<i32>) -> NumberOrNothing {
 fn vec_min(v: Vec<i32>) -> NumberOrNothing {
+    // Remember that helper function `min_i32`? Rust allows us to define such helper functions *inside* other
+    // functions. This is just a matter of namespacing, the inner function has no access to the data of the outer
+    // one. Still, being able to nicely group functions can be very useful.
+    fn min_i32(a: i32, b: i32) -> i32 {
+        if a < b { a } else { b }
+    }
+
     let mut min = Nothing;
     for e in v {
         // Notice that all we do here is compute a new value for `min`, and that it will always end
     let mut min = Nothing;
     for e in v {
         // Notice that all we do here is compute a new value for `min`, and that it will always end
@@ -44,7 +49,7 @@ fn vec_min(v: Vec<i32>) -> NumberOrNothing {
         // can express this uniformity.
         min = Number(match min {
             Nothing => e,
         // can express this uniformity.
         min = Number(match min {
             Nothing => e,
-            Number(n) => std::cmp::min(n, e)
+            Number(n) => min_i32(n, e)
         });
     }
     // The `return` keyword exists in Rust, but it is rarely used. Instead, we typically
         });
     }
     // The `return` keyword exists in Rust, but it is rarely used. Instead, we typically
index 57dc83e5d7d76ac4cc23043ad84aa2efb618d67b..e4f50be9d4694bb518d64c9fab65752ccaf7ffb5 100644 (file)
@@ -1,8 +1,6 @@
 // Rust-101, Part 02: Generic types, Traits
 // ========================================
 
 // Rust-101, Part 02: Generic types, Traits
 // ========================================
 
-use std;
-
 // Let us for a moment reconsider the type `NumberOrNothing`. Isn't it a bit annoying that we
 // had to hard-code the type `i32` in there? What if tomorrow, we want a `CharOrNothing`, and
 // later a `FloatOrNothing`? Certainly we don't want to re-write the type and all its inherent methods.
 // Let us for a moment reconsider the type `NumberOrNothing`. Isn't it a bit annoying that we
 // had to hard-code the type `i32` in there? What if tomorrow, we want a `CharOrNothing`, and
 // later a `FloatOrNothing`? Certainly we don't want to re-write the type and all its inherent methods.
@@ -114,7 +112,7 @@ pub fn vec_min<T: Minimum>(v: Vec<T>) -> SomethingOrNothing<T> {
 // To make the function usable with a `Vec<i32>`, we implement the `Minimum` trait for `i32`.
 impl Minimum for i32 {
     fn min(self, b: Self) -> Self {
 // To make the function usable with a `Vec<i32>`, we implement the `Minimum` trait for `i32`.
 impl Minimum for i32 {
     fn min(self, b: Self) -> Self {
-        std::cmp::min(self, b)
+        if self < b { self } else { b }
     }
 }
 
     }
 }
 
@@ -144,7 +142,7 @@ pub fn main() {
 
 // If this printed `3`, then you generic `vec_min` is working! So get ready for the next part.
 
 
 // If this printed `3`, then you generic `vec_min` is working! So get ready for the next part.
 
-// **Exercise 02.2**: Change your program such that it computes the minimum ofa `Vec<f32>` (where `f32` is the type
+// **Exercise 02.2**: Change your program such that it computes the minimum of a `Vec<f32>` (where `f32` is the type
 // of 32-bit floating-point numbers). You should not change `vec_min` in any way, obviously!
 
 // [index](main.html) | [previous](part01.html) | [next](part03.html)
 // of 32-bit floating-point numbers). You should not change `vec_min` in any way, obviously!
 
 // [index](main.html) | [previous](part01.html) | [next](part03.html)
index fa82eb7a21b1394cc4bd448efb5df25633733a85..9ab153dcf4176688b6afc9565e0ea75bb57f31cc 100644 (file)
@@ -6,7 +6,7 @@
 // I/O is a complicated topic, so the code to do that is not exactly pretty - but well,
 // let's get that behind us.
 
 // I/O is a complicated topic, so the code to do that is not exactly pretty - but well,
 // let's get that behind us.
 
-// I/O is provided by the module `std::io`, so we first import that.
+// I/O is provided by the module `std::io`, so we first have import that with `use`.
 // We also import the I/O *prelude*, which brings a bunch of commonly used I/O stuff
 // directly available.
 use std::io::prelude::*;
 // We also import the I/O *prelude*, which brings a bunch of commonly used I/O stuff
 // directly available.
 use std::io::prelude::*;
index 14deb89868d02da8b96fb6894b7dfedfda3606b3..663e01e8257b795f856e58c2bdffc1da64a7166e 100644 (file)
@@ -1,8 +1,6 @@
 // Rust-101, Part 04: Ownership, Borrowing
 // =======================================
 
 // Rust-101, Part 04: Ownership, Borrowing
 // =======================================
 
-use std::cmp;
-
 // Rust aims to be a "safe systems language". As a systems language, of course it
 // provides *references* (or *pointers*). But as a safe language, it has to
 // prevent bugs like this C++ snippet.
 // Rust aims to be a "safe systems language". As a systems language, of course it
 // provides *references* (or *pointers*). But as a safe language, it has to
 // prevent bugs like this C++ snippet.
@@ -67,6 +65,8 @@ fn ownership_demo() {
 // I also took the liberty to convert the function from `SomethingOrNothing` to the standard
 // library type `Option`.
 fn vec_min(v: &Vec<i32>) -> Option<i32> {
 // I also took the liberty to convert the function from `SomethingOrNothing` to the standard
 // library type `Option`.
 fn vec_min(v: &Vec<i32>) -> Option<i32> {
+    use std::cmp;
+
     let mut min = None;
     for e in v {
         // In the loop, `e` now has type `&i32`, so we have to dereference it to obtain an `i32`.
     let mut min = None;
     for e in v {
         // In the loop, `e` now has type `&i32`, so we have to dereference it to obtain an `i32`.