I know everyone says how good Rust's documentation is but I tried learning Rust with The Rust Book and found it frustrating: too long and wordy on the easy bits and without useful insight on the hard bits. I ended up buying Programming Rust by Jim Blandy [0] on a recommendation from HN comments and found it must easier to learn from. I'm already familiar with several other languages, which that book assumes, so your milage may vary.
All I've got is the 3 books that I keep referring to. I think because rust is both a high level and low level language it tries to hide some things from you, but at the same time the low level leaks through. It has the most difficult 'mental model' of any language I've used.
Here are the books, you probably know most of them, they are all good in different ways.
Going through the second chapter of O'Reilly's Programming Rust. They start out by walking you through how to build a web-server with the Iron crate, but the final code doesn't compile.
Here's the final code:
extern crate iron;
#[macro_use] extern crate mime;
extern crate router;
extern crate urlencoded;
use iron::prelude::*;
use iron::status;
use router::Router;
use std::str::FromStr;
use urlencoded::UrlEncodedBody;
fn main() {
let mut router = Router::new();
router.get("/", get_form, "root");
router.post("/gcd", post_gcd, "gcd");
println!("Serving on http://localhost:3000...");
Iron::new(router).http("localhost:3000").unwrap();
}
fn get_form(_request: &mut Request) -> IronResult<Response> {
let mut response = Response::new();
response.set_mut(status::Ok);
response.set_mut(mime!(Text/Html; Charset=Utf8));
response.set_mut(r#"
<title>GCD Calculator</title>
<form action = "gcd" method="post">
<input type="text" name="n">
<input type="text" name="n">
<button type="submit">Compute GCD</button>
</form>
"#);
Ok(response)
}
fn gcd(mut n: u64, mut m: u64) -> u64 {
assert!(n != 0 && m != 0);
while m != 0 {
if m < n {
let t = m;
m = n;
n = t;
}
m = m % n
}
n
}
fn post_gcd(request: &mut Request) -> IronResult<Response> {
let mut response = Response::new();
let form_data = match request.get_ref::<UrlEncodedBody>() {
Err(e) => {
response.set_mut(status::BadRequest);
response.set_mut(format!("Error parsing form data {:?}\n", e));
return Ok(response);
}
Ok(map) => map
};
let unparsed_numbers = match form_data.get("n") {
None => {
response.set_mut(status::BadRequest);
response.set_mut(format!("form data has no 'n' parameter\n"));
return Ok(response);
}
Some(nums) => nums
};
let mut numbers = Vec::new();
for unparsed in unparsed_numbers {
match u64::from_str(&unparsed) {
Err(_) => {
response.set_mut(status::BadRequest);
response.set_mut(
format!("Value for 'n' parameter not a number: {:?}\n",
unparsed));
return Ok(response);
}
Ok(n) => { numbers.push(n); }
}
}
let mut d = numbers[0];
for m in &numbers[1..] {
d = gcd(d, *m);
}
response.set_mut(status::Ok);
response.set_mut(mime!(Text/Html; Charset=Utf8));
response.set_mut(format!("The greatest common divisor of the numbers {:?} is <b>{}</b>\n",
numbers, d));
Ok(response)
}
...and here are the compiler errors I get:
error[E0631]: type mismatch in function arguments
--> src/main.rs:15:12
|
15 | router.get("/", get_form, "root");
| ^^^ expected signature of `for<'r, 's, 't0> fn(&'r mut iron::request::Request<'s, 't0>) -> _`
...
22 | fn get_form(_request: &mut Request) -> IronResult<Response> {
| ----------------------------------------------------------- found signature of `for<'r, 's, 't0> fn(&'r mut iron::Request<'s, 't0>) -> _`
|
= note: required because of the requirements on the impl of `iron::middleware::Handler` for `for<'r, 's, 't0> fn(&'r mut iron::Request<'s, 't0>) -> std::result::Result<iron::Response, iron::IronError> {get_form}`
error[E0631]: type mismatch in function arguments
--> src/main.rs:16:12
|
16 | router.post("/gcd", post_gcd, "gcd");
| ^^^^ expected signature of `for<'r, 's, 't0> fn(&'r mut iron::request::Request<'s, 't0>) -> _`
...
52 | fn post_gcd(request: &mut Request) -> IronResult<Response> {
| ---------------------------------------------------------- found signature of `for<'r, 's, 't0> fn(&'r mut iron::Request<'s, 't0>) -> _`
|
= note: required because of the requirements on the impl of `iron::middleware::Handler` for `for<'r, 's, 't0> fn(&'r mut iron::Request<'s, 't0>) -> std::result::Result<iron::Response, iron::IronError> {post_gcd}`
error[E0277]: expected a `std::ops::Fn<(&mut iron::Request<'_, '_>,)>` closure, found `router::Router`
--> src/main.rs:19:5
|
19 | Iron::new(router).http("localhost:3000").unwrap();
| ^^^^^^^^^ expected an `Fn<(&mut iron::Request<'_, '_>,)>` closure, found `router::Router`
|
= help: the trait `for<'r, 's, 't0> std::ops::Fn<(&'r mut iron::Request<'s, 't0>,)>` is not implemented for `router::Router`
= note: required because of the requirements on the impl of `iron::Handler` for `router::Router`
= note: required by `<iron::Iron<H>>::new`
error[E0599]: no method named `http` found for type `iron::Iron<router::Router>` in the current scope
--> src/main.rs:19:23
|
19 | Iron::new(router).http("localhost:3000").unwrap();
| ^^^^
|
= note: the method `http` exists but the following trait bounds were not satisfied:
`router::Router : iron::Handler`
error[E0277]: the trait bound `urlencoded::UrlEncodedBody: plugin::Plugin<iron::Request<'_, '_>>` is not satisfied
--> src/main.rs:55:35
|
55 | let form_data = match request.get_ref::<UrlEncodedBody>() {
| ^^^^^^^ the trait `plugin::Plugin<iron::Request<'_, '_>>` is not implemented for `urlencoded::UrlEncodedBody`
|
= help: the following implementations were found:
<urlencoded::UrlEncodedBody as plugin::Plugin<iron::request::Request<'a, 'b>>>
error: aborting due to 5 previous errors
Some errors occurred: E0277, E0599, E0631.
For more information about an error, try `rustc --explain E0277`.
error: Could not compile `iron-gcd`.
To learn more, run the command again with --verbose.
What am I doing wrong here?
by manaskarekar 2019-07-12
>the borrowing/ownership semantics of rust (at the time I looked at it) felt needlessly over complicated.
Taking a wild guess here, but it sounds like you maybe referring to issues addressed by Non-Lexical Lifetimes (NLL)?
Off-topic, but I'll just ask, is the book Programming Rust: Fast, Safe Systems Development 1st Edition [1] still relevant / worth reading (given the book is based on an older, although stable? version of Rust)?
If it isn't, does anyone know maybe if a 2nd, updated edition can be expected?
[0]: https://www.amazon.com/Programming-Rust-Fast-Systems-Develop...
[0] https://www.amazon.co.uk/Programming-Rust-Jim-Blandy/dp/1491...
All I've got is the 3 books that I keep referring to. I think because rust is both a high level and low level language it tries to hide some things from you, but at the same time the low level leaks through. It has the most difficult 'mental model' of any language I've used. Here are the books, you probably know most of them, they are all good in different ways.
https://doc.rust-lang.org/book/
https://smile.amazon.com/Programming-Rust-Fast-Systems-Development/dp/1491927283/ref=sr_1_1?keywords=programming+rust&qid=1551578981&s=gateway&sr=8-1
https://smile.amazon.com/Beginning-Rust-Professional-Carlo-Milanesi/dp/1484234677/ref=sr_1_1?keywords=beginning+rust&qid=1551579001&s=gateway&sr=8-1
Going through the second chapter of O'Reilly's Programming Rust. They start out by walking you through how to build a web-server with the Iron crate, but the final code doesn't compile.
Here's the final code:
...and here are the compiler errors I get:
What am I doing wrong here?
Taking a wild guess here, but it sounds like you maybe referring to issues addressed by Non-Lexical Lifetimes (NLL)?
Reference: https://www.amazon.com/Programming-Rust-Fast-Systems-Develop...
Edit: looks like it's a few bucks less on Amazon
[1] https://www.amazon.com/Programming-Rust-Fast-Systems-Develop... [2] https://www.amazon.com/Rust-Programming-Language-Steve-Klabn...
[1] https://www.amazon.com/Programming-Rust-Fast-Systems-Develop...