rust-lang / book

The Rust Programming Language

Home Page:https://doc.rust-lang.org/book/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Scope difference between `let` and `const` is not clear

ericmorand opened this issue · comments

  • I have searched open and closed issues and pull requests for duplicates, using these search terms:
    • constant scope
    • variable scope
  • I have checked the latest main branch to see if this has already been fixed, in this file:
    • book/src/ch03-01-variables-and-mutability.md

URL to the section(s) of the book with this problem:

https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#constants

Description of the problem:

It is said in the mentioned section that Constants can be declared in any scope, including the global scope, which makes them useful for values that many parts of code need to know about..

And earlier in the same section, it is said Like immutable variables, constants are values that are bound to a name and are not allowed to change, but there are a few differences between constants and variables..

It is not clear if the scope paragraph emphasize one of the difference between constants and variables or not. Said differently, it is not clear if variables can also be declared in every scope, or if only constants can.

After reading this section of the book, I really can't tell, and I think it is problematic when learning a new language as scope understanding is fundamental. Consequently, by just reading the book, there seems to be no fundamental differences between variables and constants that would justify the existence of the const keyword: after all, we are allowed to type variables and they are immutable by default, so using let FOO: u32 = 60 * 60 * 3; or using const FOO: u32 = 60 * 60 * 3; makes no difference.

Except of course if variables can't be declared in the global scope, which is not something that the book explicitly says.

Suggested fix:

If variables can't be declared in every scope, mention this fact in the variables section.
If variables can be declared in any scope, move the scope paragraph to the variables section. And explain what are the benefits of the const keyword over the let one.

For one point of your issue, I can agree: The book makes it not very clear, that using global variables in Rust has strong restrictions. I noticed that after reading the book, when I converted my tiny chess engine to Rust. For the difference of defining an immutable variable with let or a constant with const, the book says

The last difference is that constants may be set only to a constant expression, not the result of a value that could only be computed at runtime.

That is one of the core differences. When reading that section, I noticed no real issues, but I would agree that a beginner without some experience with other languages may wonder why constants even exist is Rust, when immutable variables work too. Also, restrictions for constants are not explained in much detail, for example that assigning values to constants that needs calling the FFI such as "const A: f64 = sin(1.0)" might not be available. But these details could be too much information for an introductory book.

I think the second part of your comment is the main issue for me: there seems to be only downsides to constants - i.e. they are defined by what they lack or can't do compared to variables.

I'm sure they come with some benefits - they would never have been specified to begin with if not to bring something that variables don't - but just from reading the book I'm unable to tell.

@ericmorand

If you are interested in some details: I just asked GPT-4 about these points, see https://chat.openai.com/share/f34ad5d2-754c-4c27-bbd1-dc3f050293c3

As I am just a Rust beginner, I can not guaranty that the GPT-4 answer is fully correct, but it looks fine for me.

A couple notes here:

  1. The section on differences is actually quite clear that the scope difference is one of the differences. Possibly it could be even clearer, with a "Second, …" at the start of the sentence “Constants can be declared…”, but it is already part of a series of statements about the differences, finishing with a “Finally” in the next paragraph. I don’t think this really needs a wording change.

  2. Having things you cannot do with a given kind of binding is actually quite useful. This idea is sometimes surprising to people when they first encounter it, but it is actually a really important one in general for software development. If I have a const, that tells both me the programmer and the compiler some important things about it vs. a let or especially a let mut, which lets me reason about it in stronger ways and lets the compiler optimize it in stronger ways.

The book’s goal here is not to tell you everything there is to know about variables or constants, but to give you the basics. I can see an argument for adding notes about scope, but you could make the same kinds of arguments for everything we are not saying here. There is a reason the book links to the Rust reference in a number of places here: if you want the detailed view of everything there is to know about these things, that is the place to go! (If you want to understand the compilation benefits, in particular, the section of the reference linked in the text of the book is a great resource!)