//
// I will assume some familiarity with programming, and hence not explain the basic
// concepts common to most languages. Instead, I will focus on what makes Rust special.
+//
+// Why Rust?
+// ---------
+//
+// When you got here, I am kind of assuming that you already decided to give Rust at
+// least a look, so that I don't have to do much convincing here ;-) . But just in
+// case, here's why I think Rust is worth learning:<br/>
+// At this time, Rust is a language with a pretty unique set of goals. Rust aims to
+// achieve C++-style control over memory and execution behavior (like, static vs. dynamic
+// dispatch), which makes it possible to construct abstractions that carry no run-time
+// cost. This is combined this with providing the comfort of high-level functional languages
+// and guaranteeing safety (as in, the program will not crash). The vast majority of existing
+// languages sacrificies one of these goals for the other. In particular, the
+// first requirement rules out a garbage collector: Rust can run "mare metal".
+// In fact, Rust rules out more classes of bugs than languages that achieve safety
+// with a GC: Besides dangling pointers and double-free, Rust also prevents issues
+// such as iterator invalidation and race conditions.
+//
//
// Prerequisites
// -------------
// Course Content
// --------------
//
-// The actual course is in the partXX.rs files. I suggest you get started with
-// [the first part](part00.html), or jump directly to where you left off:
+// The actual course is in the partXX.rs files. The part 00-03 cover some basic of the language,
+// to give you a feeling for Rust's syntax and pervasive mechanisms like pattern matching and traits.
+// Parts 04-?? introduce the heart of the language, the mechanism making it different from anything
+// else out there.
+//
+// I suggest you get started with [the first part](part00.html), or jump directly to where you left off:
//
// * [Part 00](part00.html)
// * [Part 01](part01.html)
// * [Part 02](part02.html)
// * [Part 03](part03.html)
+// * [Part 04](part04.html) (WIP)
// * (to be continued)
#![allow(dead_code, unused_imports, unused_variables)]
mod part00;
mod part01;
mod part02;
mod part03;
+mod part04;
+mod part05;
+mod part06;
// To actually run the code of some part (after filling in the blanks, if necessary), simply edit the `main`
// function.
// meaning "many shapes"). You may know something similar from C++ (where it's called
// *templates*) or Java, or one of the many functional languages. So here, we define
// a generic type `SomethingOrNothing`.
-enum SomethingOrNothing<T> {
+pub enum SomethingOrNothing<T> {
Something(T),
Nothing,
}
-use self::SomethingOrNothing::{Something,Nothing};
+// Instead of writing out all the variants, we can also just import them all at once.
+pub use self::SomethingOrNothing::*;
// What this does is to define an entire family of types: We can now write
// `SomethingOrNothing<i32>` to get back our `NumberOrNothing`, but we
// can also write `SomethingOrNothing<bool>` or even `SomethingOrNothing<SomethingOrNothing<i32>>`.
// For now, just ignore the `Copy`, we will come back to this point later.
// A `trait` is a lot like interfaces in Java: You define a bunch of functions
// you want to have implemented, and their argument and return types.
-trait Minimum : Copy {
+pub trait Minimum : Copy {
fn min(a: Self, b: Self) -> Self;
}
// we cannot call `min`. Just try it! There is no reason to believe that `T` provides such an operation.
// This is in strong contrast to C++, where the compiler only checks such details when the
// function is actually used.
-fn vec_min<T: Minimum>(v: Vec<T>) -> SomethingOrNothing<T> {
+pub fn vec_min<T: Minimum>(v: Vec<T>) -> SomethingOrNothing<T> {
let mut min = Nothing;
for e in v {
min = Something(match min {
// This also shows that we can have multiple `impl` blocks for the same type, and we
// can provide some methods only for certain instances of a generic type.
impl SomethingOrNothing<i32> {
- fn print(self) {
+ pub fn print(self) {
match self {
Nothing => println!("The number is: <nothing>"),
Something(n) => println!("The number is: {}", n),
// So much for `read_vec`. If there are any questions left, the documentation of the respective function
// should be very helpful. I will not always provide the links, as the documentation is quite easy to navigate
// and you should get used to that.
-//
-// The rest of the code dosn't change, so we just copy it.
-
-enum SomethingOrNothing<T> {
- Something(T),
- Nothing,
-}
-use self::SomethingOrNothing::{Something,Nothing};
-
-trait Minimum : Copy {
- fn min(a: Self, b: Self) -> Self;
-}
-
-fn vec_min<T: Minimum>(v: Vec<T>) -> SomethingOrNothing<T> {
- let mut min = Nothing;
- for e in v {
- min = Something(match min {
- Nothing => e,
- Something(n) => T::min(n, e)
- });
- }
- min
-}
-
-// `::std::cmp::min` is a way to refer to this function without importing `std`.
-// We could also have done `use std::cmp;` and later called `cmp::min`. Try that!
-impl Minimum for i32 {
- fn min(a: Self, b: Self) -> Self {
- ::std::cmp::min(a, b)
- }
-}
-impl SomethingOrNothing<i32> {
- fn print(self) {
- match self {
- Nothing => println!("The number is: <nothing>"),
- Something(n) => println!("The number is: {}", n),
- };
- }
-}
+// For the rest of the code, we just re-use part 02 by importing it with `use`.
+// I already sneaked a bunch of `pub` in the other module to make this possible: Only
+// items declared public can be imported elsewhere.
+use part02::{SomethingOrNothing,Something,Nothing,vec_min};
// If you update your `main.rs` to use part 03, `cargo run` should now ask you for some numbers,
// and tell you the minimum. Neat, isn't it?
// as testing whether `(self, other)` is `(Nothing, Nothing)`, which is the case exactly if
// both `self` and `other` are `Nothing`. Similar so for the second arm.
impl SomethingOrNothing<i32> {
- fn equals(self, other: Self) -> bool {
+ pub fn equals(self, other: Self) -> bool {
match (self, other) {
(Nothing , Nothing ) => true,
(Something(n), Something(m)) => n == m,
// *Hint*: You can figure out the trait bound `read_vec` needs from the documentation of `String::parse`.
// Furthermore, `std::cmp::min` works not just for `i32`, but also for `f32`.
-// [index](main.html) | [previous](part02.html) | next
+// [index](main.html) | [previous](part02.html) | [next](part04.html)