Common Programming Concepts
The notes reflect the topics in Chapter 3
Variables and Mutability
const is the constexpr in C++. But, maybe before C++17, where we can use all
kinds of stuff as constexpr. C++20 even let us declare
constexpr vector<int>! And we can use all the std algorithms on it like
std::accumulate… yummy. Rust isn’t quite there yet, at least when I write
this note.
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;Shadowing
fn main() {
let x = 5;
let x = x + 1;
{
let x = x * 2;
println!("The value of x in the inner scope is: {}", x); // 12
}
println!("The value of x is: {}", x); // 6
}This is very dope. I always want scope in Python, and it’s like a dream come true.
Data Types
fn main() {
let guess: u32 = "42".parse().expect("Not a number!"); // (1)
let some_int: i64 = 42_000; // (2)
let some_float = 2.0; // (3)
let floored = 2 / 3; // Results in 0 (4)
let f: bool = false; // with explicit type annotation
let heart_eyed_cat = '😻';
let tup: (i32, f64, u8) = (500, 6.4, 1); // type annotation can be ommited
let arr: [i32; 5] = [1, 2, 3, 4, 5]; // type annotation can be ommitted (5)
}-
The
u32must be here, just like C++ behave like thisconst auto guess = parse<uint32_t>("42"); // or const uint32_t guess = parse<>("42"); // The <> can be omitted.I’m not sure what is used in rust in the place of template though.
-
There’s no
inttype in Rust, buti8,i16,i32, etc. This makes portability a lot easier (unlike in C++ it’s all depending on implementation, the standard only requies “minimum ranges”, what’s wrong with the committe?).It checks for overflow in debug mode, and ignore it in release mode. Clever decision and I hope C++ have this too… All the standard library also offer variants to handle overflow, including checking and saturating.
-
doubleandfloatare justf64andf32in Rust. -
Sadly,
5/2 == 2in Rust, just like C++ (unlike Python). I can forsee some unfortunate numerical error caused by this already. -
This is just like
std::array. The template arguments is in the type annotation here. It does support vector-style constructor-like stuff, like this:let a = [3; 5]; // [3, 3, 3, 3, 3]Rust does have runtime index bound check for array. To avoid the performance penalty you may use iterator (introduced later).
Functions
fn main() {
let x = plus_one(5); // (1)
let y = {
let x = 3;
x + 1
};
}
fn plus_one(x: i32) -> i32 {
x + 1 // (2)
}
- Like Python, function can be declared later.
- Statement ends with
;and does not return anything. Expressions doesn’t have;and returns. This is like Matlab. Function has implicit return, like Ruby.
It’s unclear how rust handle function overloading and templated functions. Also, is there function object / lambda ?
!!! info “Spoiler! Rust has them, but not exactly”
There's no function overloading. See this
[discussion](https://internals.rust-lang.org/t/justification-for-rust-not-supporting-function-overloading-directly/7012)
for justification. TL;DR is that
[trait](10_generic_types_traits_and_lifetimes.md#traits) kinda does that, and
generic does not play along well with function overloading. Wait, what's
[generic](10_generic_types_traits_and_lifetimes.md#generic-data-types)? That's
template, without that
[SFIANE](https://en.cppreference.com/w/cpp/language/sfinae) part. Lambda is
called
[closure](13_functional_language_features_iterators_and_closures.md#closures-anonymous-functions-that-capture-their-environment)
here.
Control Flow
fn main() {
// The normal if / else
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
// if is an expression.
let condition = true;
let number = if condition { 5 } else { 6 }; // (1)
// loop and break
let mut count = 0;
'counting_up: loop { // (2)
println!("count = {}", count);
let mut remaining = 10;
loop {
println!("remaining = {}", remaining);
if remaining == 9 {
break;
}
if count == 2 {
break 'counting_up;
}
remaining -= 1;
}
count += 1;
}
println!("End count = {}", count);
// break can also return value.
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {}", result);
// While
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
// For
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {}", element);
}
}- Like Python
5 if condition else 6, or C++condition? 5 : 6. - Better
goto