TS McNamara (23) [Avatar] Offline
#1
Absolutely delighted to receive any feedback on the introductory chapter. It's had quite a large number of revisions as the table of contents has been revised. Please let me know if there is any content that should be culled or expanded.
abattisti (3) [Avatar] Offline
#2
Typos in Chapter 1
Don't know if this is the right place, but looks like there is a typo in the code sample in Section 1.1.1 (Safety):

fn for_each(v: &Vec<T>) {
     for item in 0..v.len() {
        work(v[things]);
     }
}


Line 3: "things" should probably be "item" .

In the code sample in section 1.1.3 (Control) if the integer 40 is protected by a Mutex, it is not possible to print it via "{}" (i.e. Display is not implemented for Arc<Mutex<_>>) so I guess this:

...
let d = Arc::new(Mutex::new(40));

println!("a: {}, b: {}, c: {}, d: {}", a, b, c, d);
...


should be either replaced with:

...
let d = Arc::new(40);
println!("a: {}, b: {}, c: {}, d: {}", a, b, c, d);
...


or :

...
let d = Arc::new(Mutex::new(40));

println!("a: {}, b: {}, c: {}, d: {:?}", a, b, c, d);
...


Best,
Alex
TS McNamara (23) [Avatar] Offline
#3
Typos in Chapter 1
abattisti wrote:Don't know if this is the right place, but...


Thanks very much of these corrections, Alex! I'll make sure that they're included in the next version of the MEAP. This is the perfect place for them. Thanks once again smilie
267849 (17) [Avatar] Offline
#4
"Yet the differences are sufficiently different to minimize issues..." What?

Like most natural language statements on second derivatives, this is completely inscrutable to me, how similar would the differences have to be to maximize issues?
267849 (17) [Avatar] Offline
#5
I hope the dependence on nightly will go away for the published version, the ecosystem instability caused by everything depending on some version of nightly seems to be a favorite argument among detractors. And there is half a sentence missing in "Execute rustup install nightly . This enables extra features to ."
267849 (17) [Avatar] Offline
#6
Some of the numbered notes to listing 1.1. end with a period, some don't.
267849 (17) [Avatar] Offline
#7
Section "1.1.1 Safety": I think the flow of the argument is a bit lacking here. There is no really convicing logical or rhetorical step from the compiler inserting integer overflow checks to "fearless concurrency". I know where it comes from, but it appears quite unmotivated in the actual context of the argument as presented. And it isn't helped by the fact that "imploding" is not the most common metaphor to describe the behavior of programs.

It is also not quite clear what the "similar principle" is similar to, to the fearless concurrency, the degrees of freedom or to the additional runtime checks in debug mode?

There is again something missing in "0..v.len() returns an iterator from the"
267849 (17) [Avatar] Offline
#8
Section 1.1.2 "Ergonomics":

"the preceding code would fail to compiler"

And I think this is an unconvincing example with a rather unhelpful error message. For comparision, common C compilers with sensible options will pinpoint the actual issue exactly and suggest appropriate fixes:

$ clang -Wall -Werror assign.c 
assign.c:6:9: error: using the result of an assignment as a condition without
      parentheses [-Werror,-Wparentheses]
  if (a = 10) {
      ~~^~~~
assign.c:6:9: note: place parentheses around the assignment to silence this
      warning
  if (a = 10) {
        ^
      (     )
assign.c:6:9: note: use '==' to turn this assignment into an equality comparison
  if (a = 10) {
        ^
        ==
1 error generated.


"mismatched types" can't hold a candle to this from an ergonomics standpoint. One could make a point that it is nice that the compiler doesn't need a special case rule for this error, but that makes it easier for the authors and not the users of the compiler.
267849 (17) [Avatar] Offline
#9
Section 1.1.3 "Control":

The section ends with a reference to "these three principles", which are probably safety/ergonomics/control, but that phrase is followed by three more sentences written in the form of a maxim that are not directly following from the preceeding text. So it is tempting to read the period after "principles" as a colon and the following three sentences as the list of principles referred to by "these three", ending up with two different sets of threee principles guiding the language. And the differences between the sets are different enough to be slightly confusing.
267849 (17) [Avatar] Offline
#10
Section 1.2 "Rust's big features":

With my deviant reading of the end on 1.1.3 this is the third set of three fundamental things in three pages, this may be overusing the rhetorical figure. Part of it repeats things that have already been said (but then they say that repetition is the mother of all learning, so that may be OK), and part of it may only be convincing (or even understandable) to people who already don't like Python for some very specific technical reasons.
267849 (17) [Avatar] Offline
#11
Section 1.3.2:

"Programs it won't start"
267849 (17) [Avatar] Offline
#12
Section 1.3.3:

"Rust’s referencing system are->is implemented as"

It it also not clear what referencing here refers to, it is most likely the reference counted boxed objects (Rc/Arc), but in the context of rust the word is also used for references (&) to values. So maybe "Rust's reference counted values are implemented as...". And is this even useful knowledge at this part of the journey?

The part starting with "There are design decisions" doesn't completely fit under "Size of the Language", instead it repeats parts of the other "Downsides" subsections (and 1.3.3 itself).
267849 (17) [Avatar] Offline
#13
Section 1.3.4:

"Rust is likely to have helped" - shouldn't there be a "would" somewhere in there?

"The issue lies between lines 11 & 13." The listing does not show line numbers, will this be different in the final version?
267849 (17) [Avatar] Offline
#14
1.4.4:

macOS -> iOS

267849 (17) [Avatar] Offline
#15
1.6.2:

The last four paragraphs read a bit like disconnected factoids, while I think that they were meant to be a coherent argument like this:

Systems languages tend to be powerful, but unwieldy [missing: for example by requiring explicit memory management and careful attention to the types of values. Rust tries to provide the power without this unwieldiness]. Some languages get around the memory management problems by having a GC, but rust solves this differently. And while rust is statically typed, the compiler is smart enough to take away much of the pain.

And I'd qualify it as most of the convenience of a garbage collector, at the end of the day the borrow checker is a pedantic nitpicker which most garbage colletors are not.
267849 (17) [Avatar] Offline
#16
1.1.3 Control:

The code doesn't compile:
$ rustc control.rs 
error[E0277]: the trait bound `std::sync::Mutex<{integer}>: std::fmt::Display` is not satisfied
  --> control.rs:12:51
   |
12 |   println!("a: {}, b: {}, c: {}, d: {}", a, b, c, d);
   |                                                   ^ `std::sync::Mutex<{integer}>` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
   |
   = help: the trait `std::fmt::Display` is not implemented for `std::sync::Mutex<{integer}>`
   = note: required because of the requirements on the impl of `std::fmt::Display` for `std::sync::Arc<std::sync::Mutex<{integer}>>`
   = note: required by `std::fmt::Display::fmt`

error: aborting due to previous error

$ rustc --version
rustc 1.20.0 (f3d6973f4 2017-08-27)
$
TS McNamara (23) [Avatar] Offline
#17
267849 wrote:The code doesn't compile:
println!("a: {}, b: {}, c: {}, d: {}", a, b, c, d);


Try
println!("a: {}, b: {}, c: {}, d: {:?}", a, b, c, d);
.

This makes use of Debug, rather than Display but should get you past the compiler. Apologies for the error. Niggles like that are annoying!
TS McNamara (23) [Avatar] Offline
#18
267849 wrote:Systems languages tend to be powerful, but unwieldy [missing: for example by requiring explicit memory management and careful attention to the types of values. Rust tries to provide the power without this unwieldiness]. Some languages get around the memory management problems by having a GC, but rust solves this differently. And while rust is statically typed, the compiler is smart enough to take away much of the pain.


This is an extremely helpful suggestion. I certainly want to improve chapter 1. Its a bit of a Frankenstein at the moment. Quite a lot has been pulled together from other writing. Will work hard to smooth things out.

267849 wrote:And I'd qualify it as most of the convenience of a garbage collector, at the end of the day the borrow checker is a pedantic nitpicker which most garbage colletors are not.


Fair point!
TS McNamara (23) [Avatar] Offline
#19
267849 wrote:macOS -> iOS


Controversial point. From memory, my technical ed actually asked me to remove iOS in favour of macOS. I also had ObjectiveC in there, rather than the current Swift. I believe macOS is the current name though and will better serve future readers.
TS McNamara (23) [Avatar] Offline
#20
267849 wrote:"Rust is likely to have helped" - shouldn't there be a "would" somewhere in there?


Perhaps this is a New Zealand-ism? It sounds natural to my ears, but perhaps a more conventional sentence structure would be more appropriate.

"The issue lies between lines 11 & 13." The listing does not show line numbers, will this be different in the final version?


Yes! Urgh, I thought that I had fixed all of those. Thanks very much for reporting the issue.
TS McNamara (23) [Avatar] Offline
#21
267849 wrote:Section 1.3.3:

"Rust’s referencing system are->is implemented as"

It it also not clear what referencing here refers to, it is most likely the reference counted boxed objects (Rc/Arc), but in the context of rust the word is also used for references (&) to values. So maybe "Rust's reference counted values are implemented as...". And is this even useful knowledge at this part of the journey?

The part starting with "There are design decisions" doesn't completely fit under "Size of the Language", instead it repeats parts of the other "Downsides" subsections (and 1.3.3 itself).


Agree that the language and structure is fairly muddled in this section. Some editorial surgery will be required to enhance the flow and comprehensibility. Thanks for pointing this out. It's surprisingly obvious when someone quotes your text, but very difficult when one is in the middle of writing a large block of text.
TS McNamara (23) [Avatar] Offline
#22
267849 wrote:"the preceding code would fail to compiler"

And I think this is an unconvincing example with a rather unhelpful error message. For comparision, common C compilers with sensible options will pinpoint the actual issue exactly and suggest appropriate fixes: ...


This is a fair point. I muddled around for a few hours attempting to think of an example that was concise yet compelling. At the end of the day though, I certainly recall the frustration of using the assignment operator when I meant to be comparing values when learning to code. If I get any ideas over the next few months, I will certainly inject them into the prose!

"mismatched types" can't hold a candle to this from an ergonomics standpoint. One could make a point that it is nice that the compiler doesn't need a special case rule for this error, but that makes it easier for the authors and not the users of the compiler.


I also agree that the error message could be improved.. I wonder if assignment is being used within an expression that will be evaluated by a logical test whether something more direct could be said, "Perhaps you meant == rather than =?"
TS McNamara (23) [Avatar] Offline
#23
267849 wrote:I hope the dependence on nightly will go away for the published version, the ecosystem instability caused by everything depending on some version of nightly seems to be a favorite argument among detractors. And there is half a sentence missing in "Execute rustup install nightly . This enables extra features to ."


First of all, apologies for the missing half sentence.

Yes, I am hopeful that nightlies won't be required by the time the book goes to print. It's a difficult choice for me to make. Do I pin to a version, say 1.20, and then make the book seem to be over a year old by the time it comes out? At this stage, I'll go for nightly and reconsider when the bulk of the work is done.
55925 (25) [Avatar] Offline
#24
Hello Tim,

I just ended reading the first chapter and want to give some feedback. But first of all, to put my comments into perspective: I am a Java EE developer with some contact to Scala, a bit of Haskell and others, was working with C quite some 25 years ago. Beside that, I am no native English speaker.

From what I read on the web this may be a not so rare profile for people starting to look into systems programming with Rust.

So on to topic now. While I enjoyed the first chapter in general, I had quite a hard time stumbling over the very first pages (the ones before 1.1.), which I think is a pity and a lost chance to make good initial contact with the reader.

The idea to give a quick first glance onto a short but impressive code snipped is fine. But it should lead more to a 'wow' effect than an feeling of confusion.

What were the issues?
First, we learn about a "Listing 1.1", that is "below", but indeed is relatively far on the next page. As a reader typically reads linear, especially in the introductory section of a book, we are learning too much about the code before actually seeing it.

The next thing: We read "In the example, the web framework asks the compiler ...". Oh hey, I haven't seen any code yet, but there is "the" web framework ?

Next, before even seeing any code yet, we "see the web service in action".
To do this, we have to "Install Rust via rustup.rs" - without any hint so far what that might be and what we are meant to do here. See, in the PDF rustup.rs is underlined and indeed an active link. In the print book there will be no hint about what rustup.rs is, and that this might be a URL to follow. A short mention of the words "online installer" or "installation manager" or so would be helpful.

The second step says: "... and move to the ch1-time-api directory". And now the reader is completely lost! Where now shall that be located, and where shall that come from?

The third step is to execute some code, indeed without the slightest hint for what I am experiencing here. Beside that, the next sentence misses a part "This enables extra features to [text end]".

Finally I see the console output of all that, once again: Before even seeing the code I am supposed to run.

At least we are confronted with the hidden treasure: The Code!
This is accompanied by some unfortunately very sparse explanations, and the feeling, that I as a reader may perhaps be wrong here.

Although all that is indeed meant to be introductory and not deeply explaining (which is left for later), There are some confusing points, some slightly more words could have solved.

(1) "Attributes" - You are -without explanation- introducing a Rust term here, that has a different meaning for people coming from OOP. I had to look back and forth to bring that term into connection with something that might be "compiler directives" (like in C) or "annotations" (like in Java).
(2) "Crates" - another Rust term, is explained with "packages". But that is confusing too, as in Java packages are namespaces, not compile units or libraries. As a non-native speaker I was not certain if the term "crate" should be self explanatory to me or not.
(2) (4) and (5) explain keywords to bring something "into local scope", but it is not clear what that is. One time a "crate", one time "exported members". So what is "this crate" in (4)? I am in a crate here too?
(6) "the serde crate" - is not clarifying without context. After I looked up "serde" to be the serialization-deserialization library, that became clear.
(7) Once again "the web framework". Took me quite some time to realize that this might be named "rocket", which then gave a Heureka regarding the second line and two of the "extern crate" things, as well as the message "Rocket has launched" in the console output, which looked only funny first.

After indeed spending enough time reading the next chapters and googling a bit around, that code snipped looked far less alienating. I think with only few additional words, that example can be a far more comforting introduction experience to readers without any prior Rust background.

That was my main concern for this chapter. I will note some minor issues later. Thanks for writing this book on MEAP.
TS McNamara (23) [Avatar] Offline
#25
55925 wrote:Hello Tim,

I just ended reading the first chapter and want to give some feedback. But first of all, to put my comments into perspective: I am a Java EE developer with some contact to Scala, a bit of Haskell and others, was working with C quite some 25 years ago. Beside that, I am no native English speaker.

From what I read on the web this may be a not so rare profile for people starting to look into systems programming with Rust.
....


Thank you so much for taking the time to write this comment! The chapter will certainly be revised and this feedback will help immensely.
jfs.world (109) [Avatar] Offline
#26
TS McNamara wrote:
I certainly want to improve chapter 1. Its a bit of a Frankenstein at the moment. Quite a lot has been pulled together from other writing. Will work hard to smooth things out.


Indeed pls do. Going through it, I see a lot of technical (these matter, obviously) and non-technical typos; incomplete sentences; sentences that are just awkward and place the burden on the reader to try to make sense of; ....
jfs.world (109) [Avatar] Offline
#27
TS McNamara wrote:
267849 wrote:"Rust is likely to have helped" - shouldn't there be a "would" somewhere in there?


Perhaps this is a New Zealand-ism? It sounds natural to my ears, but perhaps a more conventional sentence structure would be more appropriate.


267849: I believe the point is to make the point that it is *likely* that using Rust would have helped; rather than to say emphatically that it definitely "would" have helped.

EDIT: ok, perhaps you were thinking of something along the lines of "Using Rust would likely have helped ..."?

Not a NZer here (nor an Australian), btw. I see no real problem with the sentence, although I would agree that "Using Rust would likely have helped ..." to be a much better rewrite.
jfs.world (109) [Avatar] Offline
#28
If I may add one other point: in section 1.4.5 the example of "file formats" is used as an example of systems programming. I'm not entirely convinced. You could talk about interpreters of, or programs that use, those file formats... but file formats by themselves? Not an example of systems programming imo.
55925 (25) [Avatar] Offline
#29
1.1.1 Safety
1.:

"iterator invalidation" - an issue caused by something that is being iterated over being altered mid-way through


As a non-native speaker, I needed some time to deconstruct this sentence into the right associating parts to understand the meaning:

(something that is being iterated over) -> (it is being altered while iterating) -> (that causes an issue).

Perhaps an easier sentence would do?


2.:

The code presented here (beside the already reported issue with 'things') has a note (2) with an unfinished sentence.

Beside that, a brief remark about the range syntax would help, as this is not common for all programming languages (e.g. Java).

55925 (25) [Avatar] Offline
#30
1.3.4 Hype - mark C code, naming of brackets (, [ and {
1.:

Here you show some C code to talk about "goto fail".

That code should be notifiably marked as C code, to not confuse new readers which skim through the chapter.

2.:

There is a significant issue with the naming of the different kind of brackets '(', '{' and '[', as to non-native speakers teachers try to give some sort of regular naming in school, while there are in practice regional differences in what name means what.
(Please look here: https://en.wikipedia.org/wiki/Bracket)

So in the last to paragraphs of 1.3.4 there is a potential for confusion. I needed again some time to sort things out.

"In C, logical tests do not require brackets"

What you meant here, in my wording, is: The body(!) of a conditional expression (branch with if / loop) does not need to be in curly braces.

On the other hand, the "logical test" of the conditional expression indeed is required to be in parentheses.

And:

"Rust's grammar would have caught the bug. It does not allow logical tests without parentheses"

Well, to my reading it is indeed right the opposite: Rust does not accept parentheses around "logical tests", i.e. the checking part of the expression.

On the other hand, the body of the conditional expression must be in : curly braces!


And the right wording here is indeed essential, as Rusts syntax for conditionals is indeed not common in mainstream C-style languages.
55925 (25) [Avatar] Offline
#31
1.6.1 referring to the cargo commands in the shown boxes
"The first line has four parts"

Better: The first cargo command we typed in

Because after the box showing the three commands we got introduced to another box showing it all in action in the DOS console.

But in this box it is indeed the second line.

Likewise later in the chapter:

"The next command that you executed was cargo run"

Indeed the next command was cd hello . So you are referring to the next "cargo" command again.

But meanwhile we have seen to further boxes, one analysing the cargo new command, one showing a "tree" output.

55925 (25) [Avatar] Offline
#32
1.6.2 - Listing 1.2 - for loop and reference
Listing 1.2 shows:

for region in regions.iter() {    (5)


And the note (5) states:

"Borrow" the region variable by taking a reference,...


From what I've seen so far from Rust in this chapter, I would have expected the use of '&', when reading about a reference.

That this is missing seems confusing.
55925 (25) [Avatar] Offline
#33
1.6.2 - So what is "a macro"?
In the middle of the fifth to last paragraph you state about the exclamation mark:

In Rust, it signals the use of a macro. Macros can be thought of as[sic!] sort of fancy functions by now.



Macros were already mentioned, an when the reader looks back, it was in the introducing part before chapter 1.1.

Here it states in note (3) that #[macro_use] indicates that we want to import "macros" from another crate, here serde_derive.

Now seeing later note (6): "#[derive(Serialize)] is provided by the serde crate and automatically generates a string representation of this struct..."

The reader is easy led to believe that there is a typo and the mentioned attribute is provided by the serde_derive crate, and that the #[derive] construct is indeed a macro, as it generates some sort of stuff. Exactly what a macro is meant for, and -because of the #-sign- what a C-Preprocess macro would look like.
55925 (25) [Avatar] Offline
#34
1.7 Summary
Proposal:

Put the last bullet point ("Rust projects are not immune from all bugs") before the second-to-last ("There are three...").

Put rustup at the beginning of the tool list, because that is the first we got in contact with during setup.

Some other things -or better important terms- we learned, are:

* Attributes - not what OO people think it is, but ....
* Crates - Rusts name for something like libraries, modules ...

These terms are noteworthy, and should be made explicit again in this summary.