+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "rust-101"
version = "0.1.0"
-
@sed 's|^\(\s*//\)@|\1|;s|\s*/\*@\*/$$||;s|\(\s*\)\S.*/\*@@\*/|\1unimplemented!()|' $< | sed -f dup-unimpl.sed > $@
docs/%.html: .tmp/docs/%.rs
- @./pycco-rs $<
+ ~/.local/pipx/venvs/pycco/bin/python pycco-rs $<
## Workspace
# The generated files are shipped only for the benefit of Windows users, who
## Offline Usage
You can either read through the sources in `src/`, or generate the
-HTML in `docs/` using `make docs` (this step needs
-[Pycco](https://pycco-docs.github.io/pycco/)).
+HTML in `docs/` using `make docs`. This steps assumes `pipx install pycco` has
+been run before; it will use the pipx-created venv to import pycco.
The files `workspace/src/part*.rs` are generated by `make workspace`.
-#!/usr/bin/env python
+#!/usr/bin/env python3
# A little wrapper around pycco, to add Rust support.
import pycco, pycco_resources
from pygments import lexers, formatters
generate_documentation_called = True
result = generate_documentation_orig(*args, **kwargs)
# now patch it
- result = patch_html(result, '<link rel="stylesheet" href="pycco.css">',
- '<link rel="stylesheet" href="pycco_custom.css"><meta name="viewport" content="width=device-width">')
- result = patch_html(result, '<title>', 'Rust-101: ')
+ result = patch_html(result, b'<link rel="stylesheet" href="pycco.css">',
+ b'<link rel="stylesheet" href="pycco_custom.css"><meta name="viewport" content="width=device-width">')
+ result = patch_html(result, b'<title>', b'Rust-101: ')
## remove empty code blocks
- result = re.sub('''<div class='code'>
+ result = re.sub(b'''<div class='code'>
*<div class="highlight"><pre>(<span></span>)?</pre></div>
- *</div>''', '<!-- empty code block -->', result)
+ *</div>''', b'<!-- empty code block -->', result)
# done
return result
pycco.main.generate_documentation = generate_documentation
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "aho-corasick"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
dependencies = [
- "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr",
]
[[package]]
name = "docopt"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
dependencies = [
- "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static",
+ "regex",
+ "serde",
+ "serde_derive",
+ "strsim",
]
[[package]]
name = "lazy_static"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
[[package]]
name = "libc"
version = "0.2.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30885bcb161cf67054244d10d4a7f4835ffd58773bc72e07d35fecf472295503"
[[package]]
name = "memchr"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
dependencies = [
- "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
]
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
[[package]]
name = "regex"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
dependencies = [
- "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+ "thread_local",
+ "utf8-ranges",
]
[[package]]
name = "regex-syntax"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
[[package]]
name = "serde"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a7c6b751a2e8d5df57a5ff71b5b4fc8aaee9ee28ff1341d640dd130bb5f4f7a"
[[package]]
name = "serde_derive"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f6ca58905ebd3c3b285a8a6d4f3ac92b92c0d7951d5649b1bdd212549c06639"
dependencies = [
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote",
+ "serde_derive_internals",
+ "syn",
]
[[package]]
name = "serde_derive_internals"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
dependencies = [
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn",
+ "synom",
]
[[package]]
name = "solutions"
version = "0.1.0"
dependencies = [
- "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "docopt",
]
[[package]]
name = "strsim"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
[[package]]
name = "syn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
dependencies = [
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote",
+ "synom",
+ "unicode-xid",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
dependencies = [
- "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid",
]
[[package]]
name = "thread_local"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
dependencies = [
- "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static",
+ "unreachable",
]
[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
dependencies = [
- "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "void",
]
[[package]]
name = "utf8-ranges"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
-"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
-"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
-"checksum libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "30885bcb161cf67054244d10d4a7f4835ffd58773bc72e07d35fecf472295503"
-"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
-"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
-"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
-"checksum serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c6b751a2e8d5df57a5ff71b5b4fc8aaee9ee28ff1341d640dd130bb5f4f7a"
-"checksum serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6ca58905ebd3c3b285a8a6d4f3ac92b92c0d7951d5649b1bdd212549c06639"
-"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
-"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
-"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
-"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
-"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
-"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
-"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
-"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
-"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
}
}
-pub mod part0203 {
+pub mod part02 {
// A polymorphic (generic) "some value, or no value"
pub enum SomethingOrNothing<T> {
Something(T),
}
}
+pub mod part03 {
+ use std::io::prelude::*;
+ use std::io;
+
+ fn read_vec() -> Vec<i32> {
+ let mut vec: Vec<i32> = Vec::<i32>::new();
+ let stdin = io::stdin();
+ println!("Enter a list of numbers, one per line. End with Ctrl-D (Linux) or Ctrl-Z (Windows).");
+ for line in stdin.lock().lines() {
+ let line = line.unwrap();
+ match line.trim().parse::<i32>() {
+ Ok(num) => {
+ vec.push(num)
+ },
+ // We don't care about the particular error, so we ignore it with a `_`.
+ Err(_) => {
+ println!("What did I say about numbers?")
+ },
+ }
+ }
+
+ vec
+ }
+
+ use super::part02::{SomethingOrNothing,Something,Nothing,vec_min};
+
+ pub fn main() {
+ let vec = read_vec();
+ let min = vec_min(vec);
+ min.print2();
+ }
+
+ pub trait Print {
+ fn print(self);
+ }
+ impl Print for i32 {
+ fn print(self) {
+ print!("{}", self);
+ }
+ }
+
+ impl<T: Print> SomethingOrNothing<T> {
+ fn print2(self) {
+ match self {
+ Nothing => println!("The number is: <nothing>"),
+ Something(n) => {
+ print!("The number is: ");
+ n.print();
+ println!();
+ }
+ }
+ }
+ }
+
+ impl Print for f32 {
+ fn print(self) {
+ print!("{}", self);
+ }
+ }
+}
//
// * [The Rust Book](https://doc.rust-lang.org/stable/book/)
// * [The Rustonomicon](https://doc.rust-lang.org/nightly/nomicon/)
-// * [Rust by Example](http://rustbyexample.com/)
+// * [Rust by Example](https://doc.rust-lang.org/rust-by-example/)
// * 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.
//@ methods on an `enum` (and also on `struct`, which we will learn about later)
//@ is independent of the definition of the type. `self` is like `this` in other
//@ languages, and its type is always implicit. So `print` is now a method that
-//@ takes as first argument a `NumberOrNothing`, just like `print_number_or_nothing`.
+//@ takes `NumberOrNothing` as the first argument, just like `print_number_or_nothing`.
//@
//@ Try making `number_or_default` from above an inherent method as well!
//@ If this printed `3`, then your generic `vec_min` is working! So get ready for the next part.
// **Exercise 02.1**: 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
+// `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) | [raw source](workspace/src/part02.rs) |
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
pub trait Print {
/* Add things here */
}
+impl Print for i32 {
+ /* Add things here */
+}
impl<T: Print> SomethingOrNothing<T> {
fn print2(self) {
unimplemented!()
//@ their official name.
//@ As an example, consider a function which increments every element of a vector by 1.
-//@ The type `&mut Vec<i32>` is the type of mutable references to `vec<i32>`. Because the reference
+//@ The type `&mut Vec<i32>` is the type of mutable references to `Vec<i32>`. Because the reference
//@ is mutable, we can use a mutable iterator, providing mutable references to the elements.
fn vec_inc(v: &mut Vec<i32>) {
for e in v.iter_mut() {
//@ have aliasing (of `first` and `v`) and mutation. But this time, the bug is hidden behind the
//@ call to `head`. How does Rust solve this? If we translate the code above to Rust, it doesn't
//@ compile, so clearly we are good - but how and why?
-//@ (Notice that have to explicitly assert using //@ `unwrap` that `first` is not `None`, whereas
-//@ the C++ code above would silently dereference a //@ `NULL`-pointer. But that's another point.)
+//@ (Notice that we use `unwrap` to explicitly assert that `first` is not `None`, whereas
+//@ the C++ code above would silently dereference a `NULL`-pointer. But that's another point.)
fn rust_foo(mut v: Vec<i32>) -> i32 {
let first: Option<&i32> = head(&v);
/* v.push(42); */
// 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!
+// **Exercise 10.2**: We started the journey in Part 02 with `SomethingOrNothing<T>`, and later
+// learned about `Option<T>` in Part 04. `Option<T>` also has a `map` function.
+// [Read its documentation here.](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.map)
+// Which functions in previous parts can you rewrite to use `map` instead?
+// (Hint: read the source code of `map`, and see if the pattern appears in your own code.)
+// Bonus: [`test_invariant` in Part 05](part05.html#section-6) doesn't use `match`,
+// but can you still find a way to rewrite it with `map`?
+
//@ [index](main.html) | [previous](part09.html) | [raw source](workspace/src/part10.rs) |
//@ [next](part11.html)
//@ ## `Rc`
//@ The solution is to find some way of cloning `Callbacks` without cloning the environments. This
-//@ can be achieved with `Rc<T>`, a *reference-counted* pointer. This is is another example of a
+//@ can be achieved with `Rc<T>`, a *reference-counted* pointer. This is another example of a
//@ smart pointer. You can `clone` an `Rc` as often as you want, that doesn't affect the data it
//@ contains. It only creates more references to the same data. Once all the references are gone,
//@ the data is deleted.
//@ functions provided by `Send`. What the trait says is that types which are `Send` can be safely
//@ sent to another thread without causing trouble.
//@ Of course, all the primitive data-types are `Send`. So is `Arc`, which is why Rust accepted our
-//@ code. But `Rc` is not `Send`, and for a good reason! If had two `Rc` to the same data, and sent
+//@ code. But `Rc` is not `Send`, and for a good reason! If we had two `Rc`s to the same data, and sent
//@ one of them to another thread, things could go havoc due to the lack of synchronization.
//@
//@ Now, `Send` as a trait is fairly special. It has a so-called *default implementation*. This
//@ Rather than giving every field a name, a struct can also be defined by just giving a sequence
//@ of types (similar to how a variant of an `enum` is defined). This is called a *tuple struct*.
//@ It is often used when constructing a *newtype*, as we do here: `ConcurrentCounter` is
-//@ essentially just a new name for `Arc<Mutex<usize>>`. However, is is a locally declared types,
+//@ essentially just a new name for `Arc<Mutex<usize>>`. However, it is a locally declared types,
//@ so we can give it an inherent implementation and implement traits for it. Since the field is
//@ private, nobody outside this module can even know the type we are wrapping.
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "rust-101-workspace"
version = "0.0.0"
-