Scope

Scope in Rust works much like scope in modern Perl. Every block (if, for, while, &c.) creates a new scope. We can add a bare block for a new scope in exactly the same way ({}).

These two do the same things for the same reasons.

my $first_name = "Dean";
my $last_name = "Venture";
{
    my $first_name = "Hank";
    say "$first_name $last_name";
}
say "$first_name $last_name";

#![allow(unused_variables)]
fn main() {
let first_name = "Dean";
let last_name = "Venture";
{
    let first_name = "Hank";
    println!("{} {}", first_name, last_name);
}
println!("{} {}", first_name, last_name);
}

Both print

Hank Venture
Dean Venture

We first print "Hank Venture" because the first name is Hank in the new scope, but we can still see the Venture in the outer scope. Then we print "Dean Venture" because the inner scope is over and first name is still Dean in the outer scope.

One difference is that Rust encourages shadowing of variables (re-using a name in the same scope), but Perl does not.

my $first_name = "Dean";
my $first_name = "Hank"; # Warning!

#![allow(unused_variables)]
fn main() {
let first_name = "Dean";
let first_name = "Hank"; // first_name is *rebound* to "Hank".
}

Code like this throws a warning in Perl, but is often seen in Rust code. Note that the re-used symbol gets a completely new binding, so it can even change type.


#![allow(unused_variables)]
fn main() {
let first_name = "Dean";
let first_name = String::from("Hank");
}

Here first_name changes from a &str to a String.