Control Flow

Flow of control in Rust will look pretty familiar. In Rust, we don't use round brackets on the condition in if, while, and for as we do in Perl.

RustPerl
ifif, ternary operator
if !unless
whilewhile
loopwhile(1)
forfor, foreach
continuenext
breaklast
'label:LABEL:

In Rust, everything is an expression. There are no statements. That includes if, so we don't need a separate ternary operator.

In Perl, we might rewrite this if statement

my $name;
if ($formal) {
    $name = 'Timothy';
} else {
    $name = 'Tim';
}

with a ternary operator.

my $name = $formal ? 'Timothy' : 'Tim';

Many eschew the ternary operator, but I think that's better code. We replace a separate variable declaration, an if statement, and two assignment statements with a single assignment.

In Rust, we would probably never write the first version


#![allow(unused_variables)]
fn main() {
let name;
if formal {
    name = "Timothy";
} else {
    name = "Tim";
}
}

because the second version


#![allow(unused_variables)]
fn main() {
let name = if formal { "Timothy" } else { "Tim" };
}

just seems more natural. If if is an expression, then the first version is really going out of its way to ignore what it's returning just to repeat the name = assignment twice.

Note that neither the Perl nor the Rust versions need to stay on one line.

my $name = $formal
    ? 'Timothy'
    : 'Tim';

#![allow(unused_variables)]
fn main() {
let name = if formal {
    "Timothy"
} else {
    "Tim"
};
}

Loops

Loops are pretty much the same. If we want an infinite loop, we say loop instead of "while true".

while (1) {
    # do stuff
}

#![allow(unused_variables)]
fn main() {
loop {
    // do stuff
}
}

We don't have a C-style three-part for-loop in Rust as we do in Perl.

for (my $i = 1; $i <= 10; $i++) {
    say $i;
}

That's okay. I almost never use it in Perl, so I almost never miss it in Rust.

Rust's for is more like Perl's foreach back when we distinguished between for and foreach.

for my $i (1..10) {
    say $i;
}
fn main() {
for i in 1..=10 {
    println!("{}", i);
}
}

If we needed a three-part for-loop, we would have to write the analogous while-loop with the three separate parts.

my $i = 1;
while ($i <= 10) {
    say $i;
    $i++;
}
fn main() {
let mut i = 1;
while i <= 10 {
    println!("{}", i);
    i += 1;
}
}

I might have more to say about Rust's for later when we talk about iterators. It's really quite interesting how it works.

Maybelet

Rust also has if let and while let, which we will talk about more after we've discussed error handling. Paul Evans described them beautifully at FOSDEM 2021. At about 24:30 of this video, he proposes if(maybelet and while(maybelet for Perl 2025. That's pretty much how and why if let and while let work in Rust.