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.
Rust | Perl |
---|---|
if | if , ternary operator |
if ! | unless |
while | while |
loop | while(1) |
for | for , foreach |
continue | next |
break | last |
'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.