Rust by Example Question(s)


#1

Example 3.2.3. (linked list) depends on: use List::*;
which defines somewhere Cons and Nil.
Looking into the std library, I see only doubly linked lists etc.
Am I looking in the wrong place?
Where are these simple List definitions?


#2

Into the same file!


#3

It did cross my mind but then I am confused why we need the use declaration at the top?


#4

To avoid writing every time List::Cons and List::Nil.
With the use statement you are saying that every time you write Nil you mean List::Nil and Cons == List::Cons


#5

OK, I get it. Many thanks! I did not realise it serves both for external imports and this purpose also.


#6

Actually, no, it does not do anything for “external imports”.

Unlike in C, C++, Python, Swift, etc. where you need to include or import parts of the standard library in order to use it, in Rust – much like in Java or C# – you have the whole standard library always available to you, so you can use it without any imports or uses:

fn main() {
    let mut set = std::collections::HashSet::new();
    set.insert(42);
    println!("{}", set.contains(&42));
}

But it can be tiresome to always specify the fully qualified name for types & functions, so you use the use statement:

use std::collections::HashSet;

fn main() {
    let mut set = HashSet::new();
    set.insert(42);
    println!("{}", set.contains(&42));
}

(in this case it didn’t make the program shorter, but you get the idea). That’s all use does, it brings the thing into the current scope.

Some of the most frequently used things (such as Option, Vec and Box) are used automatically without you having to do it explicitly. Read more about it here: https://doc.rust-lang.org/std/prelude/


#7

Right, now it finally makes sense! :sunglasses:
It might be good to paste what you have just written into Rust by Examples somewhere near the front.


#8

It’s worth noting that the standard library is available as std in the main file only (lib.rs or main.rs). Other modules need to refer to it as ::std or use use statements.


#9

It’s covered in http://rustbyexample.com/custom_types/enum/enum_use.html, two sections before the bit you were reading.


#10

Yes, I am aware of that. I meant that about the standard library, that it is available in main.rs (and lib.rs).


#11

Another week, another question:
Why is it necessary to use “reference” instead of the usual “&” on the left hand side of assignments?


#12

ref is used for destructuring references. In normal cases the destructuring pattern is the same as the constructing pattern (e.g. match x { Some(val) => Some("hello world!"), ... }). However, since & has a special meaning on the left hand side the Rust team had to use an alternate keyword ref.


#13

Because & and ref mean different things:

let a = 1;  // a is 1
let b = &1;  // b is &1 (a reference to a temporary variable)
let &c = &1;  // c is 1
let ref d = 1;  // d is &1
let ref e = &1; // e is &&1

& in patterns dereferences the value, whereas ref makes a reference.


#14

Effectively,

let &a = expr;
// is the same as
let a = *expr;

// and

let ref b = expr;
// is the same as
let b = &expr;

So why is there a need for the first form, you may wonder. The answer is that it’s useful with more complicated patterns:

let optional = Some(value);
if let Some(ref val_ref) = optional {
    // val_ref if &value
}

// by the way, patterns are used in a lot more places than just `let` bindings
(0..100).filter(|&i| i % 3 != 0)

#15

Thanks @bugaevc, that is a really good simple explanation!