From: Ralf Jung Date: Sun, 23 Aug 2015 11:15:28 +0000 (+0200) Subject: more https X-Git-Url: https://git.ralfj.de/rust-101.git/commitdiff_plain/6b347ac8c0f8710bd0ca42d20d32511fcb53f188?ds=inline;hp=68122e49effdf4d4210ddc0ebec69af88b50812a more https --- diff --git a/src/main.rs b/src/main.rs index c20a47d..e1e4a64 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ // =================== // // This is [Rust-101](https://www.ralfj.de/projects/rust-101/), a small tutorial for -// the [Rust language](http://www.rust-lang.org/). It is intended to be an interactive, +// the [Rust language](https://www.rust-lang.org/). It is intended to be an interactive, // hands-on course: I believe the only way to *really* learn a language is to write code // in it, so you should be coding during the course. // @@ -35,12 +35,12 @@ // --------------- // // You will need to have Rust installed, of course. It is available for download on -// [the Rust website](http://www.rust-lang.org/). Make sure you get at least version 1.2. +// [the Rust website](https://www.rust-lang.org/). Make sure you get at least version 1.2. // More detailed installation instructions are provided in // [the second chapter of The Book](https://doc.rust-lang.org/stable/book/installing-rust.html). // This will also install `cargo`, the tool responsible for building rust projects (or *crates*). // -// Next, fetch the Rust-101 source code from the [git repository](http://www.ralfj.de/git/rust-101.git) +// Next, fetch the Rust-101 source code from the [git repository](https://www.ralfj.de/git/rust-101.git) // (also available [on GitHub](https://github.com/RalfJung/rust-101), and as a // [zip archive](https://github.com/RalfJung/rust-101/archive/master.zip) in case you don't have git installed). // @@ -117,4 +117,4 @@ fn main() { // * [Rust by Example](http://rustbyexample.com/) // * The [Rust Subreddit](https://www.reddit.com/r/rust/) // * A [collection of links](https://github.com/ctjhoa/rust-learning) to blog posts, articles, videos, etc. for learning Rust. -// * For the IRC channel and other forums, see the "Community" section of the [Rust Documentation index](http://doc.rust-lang.org/index.html) +// * For the IRC channel and other forums, see the "Community" section of the [Rust Documentation index](https://doc.rust-lang.org/index.html) diff --git a/src/part02.rs b/src/part02.rs index bd8abf0..1af74fc 100644 --- a/src/part02.rs +++ b/src/part02.rs @@ -22,7 +22,7 @@ pub use self::SomethingOrNothing::*; type NumberOrNothing = SomethingOrNothing; //@ However, we can also write `SomethingOrNothing` or even `SomethingOrNothing>`. //@ In fact, such a type is so useful that it is already present in the standard library: It's called an -//@ *option type*, written `Option`. Go check out its [documentation](http://doc.rust-lang.org/stable/std/option/index.html)! +//@ *option type*, written `Option`. Go check out its [documentation](https://doc.rust-lang.org/stable/std/option/index.html)! //@ (And don't worry, there's indeed lots of material mentioned there that we did not cover yet.) // ## Generic `impl`, Static functions diff --git a/src/part03.rs b/src/part03.rs index ef8ab92..16527a2 100644 --- a/src/part03.rs +++ b/src/part03.rs @@ -29,14 +29,14 @@ fn read_vec() -> Vec { //@ for that, but there is a catch: What happens if there is some other piece of code running //@ 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](http://doc.rust-lang.org/stable/std/io/struct.Stdin.html) for more + //@ it. (See [the documentation](https://doc.rust-lang.org/stable/std/io/struct.Stdin.html) for 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`. //@ The problem with I/O is that it can always go wrong. The type of `line` is a lot like `Option` ("a `String` or //@ nothing"), but in the case of "nothing", there is additional information about the error. - //@ Again, I recommend to check [the documentation](http://doc.rust-lang.org/stable/std/io/type.Result.html). + //@ Again, I recommend to check [the documentation](https://doc.rust-lang.org/stable/std/io/type.Result.html). //@ You will see that `io::Result` is actually just an alias for `Result`, so click on that to obtain //@ the list of all constructors and methods of the type. diff --git a/src/part06.rs b/src/part06.rs index 8161d2d..4dff55c 100644 --- a/src/part06.rs +++ b/src/part06.rs @@ -145,6 +145,6 @@ fn rust_foo(mut v: Vec) -> i32 { //@ are used correctly, *while looking only at the function type*. At no point in our analysis of `rust_foo` did //@ we have to look *into* `head`. That's, of course, crucial if we want to separate library code from application code. //@ Most of the time, we don't have to explicitly add lifetimes to function types. This is thanks to *lifetimes elision*, -//@ where Rust will automatically insert lifetimes we did not specify, following some [simple, well-documented rules](http://doc.rust-lang.org/stable/book/lifetimes.html#lifetime-elision). +//@ where Rust will automatically insert lifetimes we did not specify, following some [simple, well-documented rules](https://doc.rust-lang.org/stable/book/lifetimes.html#lifetime-elision). //@ [index](main.html) | [previous](part05.html) | [next](part07.html) diff --git a/src/part07.rs b/src/part07.rs index 4c143d5..49f6900 100644 --- a/src/part07.rs +++ b/src/part07.rs @@ -62,8 +62,8 @@ impl PartialEq for BigInt { //@ Since implementing `PartialEq` is a fairly mechanical business, you can let Rust automate this //@ by adding the attribute `derive(PartialEq)` to the type definition. In case you wonder about -//@ the "partial", I suggest you check out the documentation of [`PartialEq`](http://doc.rust-lang.org/std/cmp/trait.PartialEq.html) -//@ and [`Eq`](http://doc.rust-lang.org/std/cmp/trait.Eq.html). `Eq` can be automatically derived as well. +//@ the "partial", I suggest you check out the documentation of [`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html) +//@ and [`Eq`](https://doc.rust-lang.org/std/cmp/trait.Eq.html). `Eq` can be automatically derived as well. // Now we can compare `BigInt`s. Rust treats `PratialEq` special in that it is wired to the operator `==`: //@ That operator can not be used on our numbers! Speaking in C++ terms, we just overloaded the `==` operator @@ -71,7 +71,7 @@ impl PartialEq for BigInt { //@ functions depending on the type of the argument). Instead, one typically finds (or defines) a //@ trait that catches the core characteristic common to all the overloads, and writes a single //@ function that's generic in the trait. For example, instead of overloading a function for all -//@ the ways a string can be represented, one writes a generic functions over [ToString](http://doc.rust-lang.org/std/string/trait.ToString.html). +//@ the ways a string can be represented, one writes a generic functions over [ToString](https://doc.rust-lang.org/std/string/trait.ToString.html). //@ Usually, there is a trait like this that fits the purpose - and if there is, this has the great //@ advantage that any type *you* write, that can convert to a string, just has to implement //@ that trait to be immediately usable with all the functions out there that generalize over `ToString`. @@ -113,7 +113,7 @@ fn test_min() { //@ that users can understand, while `Debug` is meant to show the internal state of data and targeted at //@ the programmer. The latter is what we want for `assert_eq!`, so let's get started. -// All formating is handled by [`std::fmt`](http://doc.rust-lang.org/std/fmt/index.html). I won't explain +// All formating is handled by [`std::fmt`](https://doc.rust-lang.org/std/fmt/index.html). I won't explain // all the details, and refer you to the documentation instead. use std::fmt; diff --git a/src/part08.rs b/src/part08.rs index 7b471b9..ad29565 100644 --- a/src/part08.rs +++ b/src/part08.rs @@ -17,7 +17,7 @@ fn overflowing_add(a: u64, b: u64, carry: bool) -> (u64, bool) { //@ The reason for this is that many serious security vulnerabilities have been caused by integer overflows, so just assuming //@ "per default" that they are intended is dangerous.
//@ If you explicitly *do* want an overflow to happen, you can call the `wrapping_add` - //@ function (see [the documentation](http://doc.rust-lang.org/stable/std/primitive.u64.html#method.wrapping_add), + //@ function (see [the documentation](https://doc.rust-lang.org/stable/std/primitive.u64.html#method.wrapping_add), //@ there are similar functions for other arithmetic operations). There are also similar functions //@ `checked_add` etc. to enforce the overflow check. let sum = a.wrapping_add(b); @@ -57,7 +57,7 @@ fn test_overflowing_add() { impl ops::Add for BigInt { //@ Besides static functions and methods, traits can contain *associated types*: This is a type chosen by every particular implementation //@ of the trait. The methods of the trait can then refer to that type. In the case of addition, it is used to give the type of the result. - //@ (Also see the [documentation of `Add`](http://doc.rust-lang.org/stable/std/ops/trait.Add.html).) + //@ (Also see the [documentation of `Add`](https://doc.rust-lang.org/stable/std/ops/trait.Add.html).) //@ //@ In general, you can consider the two `BigInt` given above (in the `impl` line) *input* types of trait search: When //@ `a + b` is invoked with `a` having type `T` and `b` having type `U`, Rust tries to find an implementation of `Add` for diff --git a/src/part09.rs b/src/part09.rs index 5a4f666..40e32a2 100644 --- a/src/part09.rs +++ b/src/part09.rs @@ -5,7 +5,7 @@ use part05::BigInt; //@ In the following, we will look into the iterator mechanism of Rust and make our `BigInt` compatible //@ with the `for` loops. Of course, this is all about implementing certain traits again. In particular, -//@ an iterator is something that implements the `Iterator` trait. As you can see in [the documentation](http://doc.rust-lang.org/stable/std/iter/trait.Iterator.html), +//@ an iterator is something that implements the `Iterator` trait. As you can see in [the documentation](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html), //@ this trait mandates a single function `next` returning an `Option`, where `Item` is an //@ associated type chosen by the implementation. (There are many more methods provided for `Iterator`, //@ but they all have default implementations, so we don't have to worry about them right now.) @@ -121,7 +121,7 @@ fn iter_invalidation_demo() { // ## Iterator conversion trait //@ If you closely compare the `for` loop in `main` above, with the one in `part06::vec_min`, you will notice that we were able to write //@ `for e in v` earlier, but now we have to call `iter`. Why is that? Well, the `for` sugar is not actually tied to `Iterator`. -//@ Instead, it demands an implementation of [`IntoIterator`](http://doc.rust-lang.org/stable/std/iter/trait.IntoIterator.html). +//@ Instead, it demands an implementation of [`IntoIterator`](https://doc.rust-lang.org/stable/std/iter/trait.IntoIterator.html). //@ That's a trait of types that provide a *conversion* function into some kind of iterator. These conversion traits are a frequent //@ pattern in Rust: Rather than demanding that something is an iterator, or a string, or whatever; one demands that something //@ can be converted to an iterator/string/whatever. This provides convenience similar to overloading of functions: The function diff --git a/src/part10.rs b/src/part10.rs index 02fb828..0522cb0 100644 --- a/src/part10.rs +++ b/src/part10.rs @@ -131,12 +131,12 @@ fn print_enumerated(v: &Vec) { // And as a final example, one can also collect all elements of an iterator, and put them, e.g., in a vector. fn filter_vec_by_divisor(v: &Vec, divisor: i32) -> Vec { //@ Here, the return type of `collect` is inferred based on the return type of our function. In general, it can return anything implementing - //@ [`FromIterator`](http://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html). Notice that `iter` gives us an iterator over + //@ [`FromIterator`](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html). Notice that `iter` gives us an iterator over //@ borrowed `i32`, but we want to own them for the result, so we insert a `map` to dereference. v.iter().map(|n| *n).filter(|n| *n % divisor == 0).collect() /*@*/ } -// **Exercise 10.1**: Look up the [documentation of `Iterator`](http://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) to learn about more functions +// **Exercise 10.1**: Look up the [documentation of `Iterator`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) to learn about more functions // that can act on iterators. Try using some of them. What about a function that sums the even numbers of an iterator? Or a function that computes the // product of those numbers that sit at odd positions? A function that checks whether a vector contains a certain number? Whether all numbers are // smaller than some threshold? Be creative! diff --git a/src/part11.rs b/src/part11.rs index 9d093e3..211cda5 100644 --- a/src/part11.rs +++ b/src/part11.rs @@ -102,7 +102,7 @@ pub fn main() { //@ a *pointer* to such a type (be it a `Box` or a borrow) will need to complete this information. We say that pointers to //@ trait objects are *fat*. They store not only the address of the object, but (in the case of trait objects) also a *vtable*: A //@ table of function pointers, determining the code that's run when a trait method is called. There are some restrictions for traits to be usable -//@ as trait objects. This is called *object safety* and described in [the documentation](http://doc.rust-lang.org/stable/book/trait-objects.html) and [the reference](http://doc.rust-lang.org/reference.html#trait-objects). +//@ as trait objects. This is called *object safety* and described in [the documentation](https://doc.rust-lang.org/stable/book/trait-objects.html) and [the reference](https://doc.rust-lang.org/reference.html#trait-objects). //@ In case of the `FnMut` trait, there's only a single action to be performed: Calling the closure. You can thus think of a pointer to `FnMut` as //@ a pointer to the code, and a pointer to the environment. This is how Rust recovers the typical encoding of closures as a special case of a more //@ general concept. diff --git a/src/part13.rs b/src/part13.rs index 9f42b82..861ec2d 100644 --- a/src/part13.rs +++ b/src/part13.rs @@ -167,7 +167,7 @@ pub fn main() { //@ sure that the callbacks do not reference any pointers that might become invalid? This is just as crucial for spawning //@ a thread: In general, that thread could last for much longer than the current stack frame. Thus, it must not use //@ any pointers to data in that stack frame. This is achieved by requiring the `FnOnce` closure passed to `thread::spawn` -//@ to be valid for lifetime `'static`, as you can see in [its documentation](http://doc.rust-lang.org/stable/std/thread/fn.spawn.html). +//@ to be valid for lifetime `'static`, as you can see in [its documentation](https://doc.rust-lang.org/stable/std/thread/fn.spawn.html). //@ This avoids another kind of data race, where the thread's access races with the callee deallocating its stack frame. //@ It is only thanks to the concept of lifetimes that this can be expressed as part of the type of `spawn`. diff --git a/src/part14.rs b/src/part14.rs index 189a906..2105838 100644 --- a/src/part14.rs +++ b/src/part14.rs @@ -69,7 +69,7 @@ fn sort_array() { // ## External Dependencies //@ This leaves us with just one more piece to complete rgrep: Taking arguments from the command-line. We could now directly work on -//@ [`std::env::args`](http://doc.rust-lang.org/stable/std/env/fn.args.html) to gain access to those arguments, and this would become +//@ [`std::env::args`](https://doc.rust-lang.org/stable/std/env/fn.args.html) to gain access to those arguments, and this would become //@ a pretty boring lesson in string manipulation. Instead, I want to use this opportunity to show how easy it is to benefit from //@ other people's work in your program. //@ diff --git a/src/part15.rs b/src/part15.rs index 99eb3be..19ce603 100644 --- a/src/part15.rs +++ b/src/part15.rs @@ -11,7 +11,7 @@ use std::thread; //@ which we already discussed in a single-threaded context in part 12. //@ //@ ## `Mutex` -//@ The most basic type for interior mutability that supports concurrency is [`Mutex`](http://doc.rust-lang.org/stable/std/sync/struct.Mutex.html). +//@ The most basic type for interior mutability that supports concurrency is [`Mutex`](https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html). //@ This type implements *critical sections* (or *locks*), but in a data-driven way: One has to specify //@ the type of the data that's protected by the mutex, and Rust ensures that the data is *only* accessed //@ through the mutex. In other words, "lock data, not code" is actually enforced by the type system, which @@ -103,7 +103,7 @@ pub fn main() { // the data inside the lock. Change the code above to do that. Try using `unwrap_or_else` for this job. //@ ## `RwLock` -//@ Besides `Mutex`, there's also [`RwLock`](http://doc.rust-lang.org/stable/std/sync/struct.RwLock.html), which +//@ Besides `Mutex`, there's also [`RwLock`](https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html), which //@ provides two ways of locking: One that grants only read-only access, to any number of concurrent readers, and another one //@ for exclusive write access. Notice that this is the same pattern we already saw with shared vs. mutable borrows. Hence //@ another way of explaining `RwLock` is to say that it is like `RefCell`, but works even for concurrent access. Rather than @@ -119,7 +119,7 @@ pub fn main() { //@ //@ In part 13, we talked about types that are marked `Send` and thus can be moved to another thread. However, we did *not* //@ talk about the question whether a borrow is `Send`. For `&mut T`, the answer is: It is `Send` whenever `T` is send. -//@ `&mut` allows moving values back and forth, it is even possible to [`swap`](http://doc.rust-lang.org/stable/std/mem/fn.swap.html) +//@ `&mut` allows moving values back and forth, it is even possible to [`swap`](https://doc.rust-lang.org/stable/std/mem/fn.swap.html) //@ the contents of two mutably borrowed values. So in terms of concurrency, sending a mutable borrow is very much like //@ sending full ownership, in the sense that it can be used to move the object to another thread. //@ diff --git a/src/part16.rs b/src/part16.rs index dc26369..e80d80a 100644 --- a/src/part16.rs +++ b/src/part16.rs @@ -55,7 +55,7 @@ pub struct LinkedList { //@ Clearly, that's an unsafe operation and must only be used with great care - or even better, not at all. Seriously. //@ If at all possible, you should never use `transmute`.
//@ We are making the assumption here that a `Box` and a raw pointer have the same representation in memory. In the future, -//@ Rust will [provide](http://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#method.from_raw) such [operations](http://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#method.into_raw) in the standard library, but the exact API is still being fleshed out. +//@ Rust will [provide](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#method.from_raw) such [operations](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#method.into_raw) in the standard library, but the exact API is still being fleshed out. //@ We declare `raw_into_box` to be an `unsafe` function, telling Rust that calling this function is not generally safe. //@ This grants us the unsafe powers for the body of the function: We can dereference raw pointers, and - most importantly - we diff --git a/workspace/src/part07.rs b/workspace/src/part07.rs index 75bd0cc..3ea4cc0 100644 --- a/workspace/src/part07.rs +++ b/workspace/src/part07.rs @@ -61,7 +61,7 @@ fn test_min() { // ## Formatting -// All formating is handled by [`std::fmt`](http://doc.rust-lang.org/std/fmt/index.html). I won't explain +// All formating is handled by [`std::fmt`](https://doc.rust-lang.org/std/fmt/index.html). I won't explain // all the details, and refer you to the documentation instead. use std::fmt; diff --git a/workspace/src/part10.rs b/workspace/src/part10.rs index c955394..8fc650f 100644 --- a/workspace/src/part10.rs +++ b/workspace/src/part10.rs @@ -92,7 +92,7 @@ fn filter_vec_by_divisor(v: &Vec, divisor: i32) -> Vec { unimplemented!() } -// **Exercise 10.1**: Look up the [documentation of `Iterator`](http://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) to learn about more functions +// **Exercise 10.1**: Look up the [documentation of `Iterator`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) to learn about more functions // that can act on iterators. Try using some of them. What about a function that sums the even numbers of an iterator? Or a function that computes the // product of those numbers that sit at odd positions? A function that checks whether a vector contains a certain number? Whether all numbers are // smaller than some threshold? Be creative!