1 - 6 The Rust Programming Language Flashcards

(174 cards)

1
Q

What is the purpose of the rustfmt tool?

A

It is an automatic formatter that ensures your code follows the standard Rust community style.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

How does a Rust macro differ fundamentally from a function?

A

Macros are used to write code that generates other code, and they do not always follow the same rules as functions.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What command is used to manually compile a Rust source file?

A

rustc filename.rs

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What is the immediate output of a successful Rust compilation?

A

A binary executable file.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What does it mean that Rust is an ahead-of-time compiled language?

A

You can compile a program and give the executable to someone else, and they can run it without having Rust installed.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What is the purpose of the .pdb file on Windows?

A

It contains debugging information used by development tools.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Why might you use Cargo instead of rustc as your project grows?

A

Cargo helps manage complex project options, dependencies, and makes it easier to share code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What is the command to create a new project using Cargo?

A

cargo new project_name

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

In a Cargo project, where does the source code (like main.rs) live?

A

Inside the src directory.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What does the Cargo.toml file do?

A

It is the configuration file for the project, written in TOML format.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What does TOML stand for?

A

Tom’s Obvious, Minimal Language.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is the purpose of the [package] section in Cargo.toml?

A

It contains configuration metadata needed to compile the program, such as the name, version, and edition.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Where do you list the external crates your project needs in Cargo.toml?

A

Under the [dependencies] section.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What is the main difference between the top-level directory and the src directory?

A

The top-level is for configuration, READMEs, and licenses; src is strictly for source code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What command compiles a Cargo project?

A

cargo build

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Where does Cargo store the executable file by default?

A

In the target/debug/ directory.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Why do developers use cargo check instead of cargo build during development?

A

It is much faster because it verifies the code compiles without the time-consuming step of producing an executable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

What is the purpose of the Cargo.lock file?

A

It keeps track of the exact versions of dependencies to ensure builds are reproducible.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Who (or what) is responsible for managing the contents of Cargo.lock?

A

Cargo (users should not edit this file manually).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

What happens if you run cargo run and the source code hasn’t changed since the last build?

A

Cargo skips the compilation step and runs the existing binary immediately.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

What is the primary benefit of the target/debug/ folder in the root directory for binaries?

A

It keeps the project root clean and organizes build artifacts separately from source code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

What is the prelude in Rust?

A

A set of items defined in the standard library that Rust automatically brings into the scope of every program.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Which library provides features for accepting user input?

A

The std::io library.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Where can you find a complete list of everything included in the prelude?

A

In the official Rust standard library documentation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
In the line let mut guess = String::new();, what is guess bound to?
A new, empty instance of a String.
26
What does the :: syntax indicate in String::new()?
It indicates that new is an associated function of the String type.
27
What is an "associated function" in Rust?
A function that is implemented on a type (like a static method in other languages) rather than on a specific instance of that type.
28
What kind of string is String (as opposed to a string literal)?
String is a heap-allocated, growable buffer. It is a UTF-8 encoded bit of text provided by the standard library.
29
What is the specific behavior of the method? io::stdin().read_line(&mut buffer)
It takes the user's terminal input and appends it to the provided string buffer without overwriting existing data.
30
In Rust, what is a reference (signified by the & symbol)?
A way to let multiple parts of code access one piece of data in memory without making a copy of that data.
31
In Rust, what is an enumeration (or enum)?
A type that can be in one of multiple possible states, called variants.
32
When calling .expect() on a Result, what happens if the value is an Err variant?
The program crashes (panics) and displays the message passed as an argument to expect.
33
When calling .expect() on a Result, what happens if the value is an Ok variant?
It extracts the successful return value from the Ok variant and returns it to the program.
34
What specific information does io::stdin().read_line() return inside its Ok variant?
The number of bytes in the user's input.
35
What is the difference between a binary crate and a library crate?
A binary crate is an executable program; a library crate contains code meant to be used in other programs and cannot be run on its own.
36
What is the purpose of the Cargo.lock file?
It ensures reproducible builds by recording the exact versions of dependencies used, so the project builds the same way every time.
37
How does Cargo handle dependencies if you run cargo build and no changes have been made to the code or Cargo.toml?
Cargo realizes nothing has changed and exits without recompiling the dependencies or the project code.
38
What command should be used to ignore the Cargo.lock file and update dependencies to the latest compatible versions?
cargo update
39
If you want to use a new major version of a crate (e.g., moving from 0.8.x to 0.9.x), where must you update the version number?
In the [dependencies] section of the Cargo.toml file.
40
Why is it common practice to check the Cargo.lock file into source control?
To ensure that everyone working on the project, and any automated build systems, use the exact same versions of all dependencies.
41
What are the individual components of a match expression called?
Arms.
42
How does Rust evaluate a value against a match expression?
It checks the value against each arm's pattern in turn (top to bottom).
43
What is a key safety benefit of using Rust’s match construct?
It ensures that you handle all possible situations or patterns the value might encounter.
44
What does the trim() method do to a String instance?
It removes any whitespace, including newline characters (\n or \r\n), from the beginning and end.
45
What is the purpose of the .parse() method in Rust?
It converts a string into another type (such as a numerical type).
46
How do you explicitly annotate a variable with a type in Rust?
By adding a colon and the type name after the variable name (e.g., let x: u32).
47
What is a strict requirement for the declaration of a constant regarding its type?
The type of the value must always be annotated (e.g., : u32).
48
What is the naming convention for constants in Rust?
All uppercase letters with underscores between words (SCREAMING_SNAKE_CASE).
49
Where can constants be declared in a Rust program?
In any scope, including the global scope.
50
What kind of value can be assigned to a constant?
Only a constant expression (a value that can be evaluated at compile time).
51
How long do constants remain valid in a program?
For the entire time the program runs, within the scope they were declared.
52
What is a major advantage of shadowing over using a mut variable?
Shadowing allows you to change the type of a value while reusing the same variable name.
53
In the code let spaces = " "; let spaces = spaces.len(); what are the types of the first and second spaces?
The first is a string type (&str); the second is a numeric type (usually usize).
54
How many bytes does the Rust char type occupy?
4 bytes (it represents a Unicode scalar value).
55
What is the main difference between a Tuple and an Array?
A Tuple can hold multiple different types; an Array must hold values of the same type.
56
Can the size of a primitive Array be changed after declaration?
No, Arrays in Rust have a fixed length.
57
What do isize and usize depend on?
The architecture of the computer running the program (32-bit vs. 64-bit).
58
What is a "scalar" type in computer science/Rust?
A type that represents a single, atomic value.
59
What are the four primary scalar types in Rust?
Integers, floating-point numbers, Booleans, and characters.
60
How can you use a type suffix with a numeric literal in Rust?
By appending the type directly to the number (e.g., 57u8 for an unsigned 8-bit integer).
61
What is the purpose of using an underscore (_) in a Rust number literal?
It serves as a visual separator to make large numbers easier to read (e.g., 1_000 is the same as 1000).
62
What prefix is used to write an integer literal in Hexadecimal format?
0x (e.g., 0xff).
63
What prefix is used to write an integer literal in Binary format?
0b (e.g., 0b1111_0000).
64
What prefix is used to write an integer literal in Octal format?
0o (e.g., 0o77).
65
How do you write a "Byte" literal in Rust, and what type does it represent?
Use the b prefix with single quotes (e.g., b'A'); it represents a u8 only.
66
What is integer overflow?
When a value is assigned to a variable that is outside the range of its defined numeric type.
67
How does Rust handle integer overflow in debug mode?
It includes checks that cause the program to panic (crash with an error) at runtime.
68
Which method family allows you to explicitly wrap a value in all compilation modes?
The wrapping_* methods (e.g., wrapping_add).
69
Which method family returns None if an overflow occurs?
The checked_* methods.
70
Which method family returns a tuple containing the value and a Boolean indicating if overflow occurred?
The overflowing_* methods.
71
What do saturating_* methods do when an overflow occurs?
They "cap" the value at the type's minimum or maximum limit (it stays at the limit instead of wrapping).
72
How do the literal syntaxes for a char and a string differ in Rust?
char literals use single quotation marks (e.g., 'a'), while string literals use double quotation marks (e.g., "a").
73
What is the memory size of a Rust char and what does it represent?
It is 4 bytes in size and represents a Unicode scalar value.
74
What range of characters can the Rust char type represent beyond standard ASCII?
It can represent accented letters, non-Latin characters (such as Chinese, Japanese, or Korean), emojis, and zero-width spaces.
75
How do you destructure a tuple in Rust to bind its individual parts to separate variables?
Use the let keyword with a pattern, for example: let tup: (i32, f64, u8) = (500, 6.4, 1); let (x, y, z) = tup;
76
What is a defining characteristic of a Rust array's size?
It is fixed; an array cannot grow or shrink in size once defined.
77
What is the primary difference between a vector and an array regarding memory allocation and flexibility?
A vector's contents live on the heap and can change in size, while an array lives on the stack and has a fixed size.
78
According to general Rust guidelines, which collection should you use if you are unsure whether an array or a vector is appropriate?
A vector.
79
What is a statement in Rust?
An instruction that performs an action but does not return a value.
80
What is an expression in Rust?
A piece of code that evaluates to a resultant value.
81
Why is the distinction between statements and expressions particularly important in Rust?
Because Rust is an expression-based language, and this distinction affects how function bodies and control flow are structured.
82
Do return values in Rust functions require a name in the function declaration?
No, only the type of the return value must be declared.
83
True or False: Most Rust functions return the last expression implicitly.
True.
84
Does Rust have a ternary operator (e.g., condition ? a : b)?
No; in Rust, if is an expression that can return a value, making a separate ternary operator unnecessary.
85
What is the syntax for assigning a value to a variable using an if expression?
let variable = if condition { value1 } else { value2 };
86
How can you return a value from a loop block to a variable?
By providing the value after the break keyword (e.g., break counter * 2;).
87
What happens if you use a non-boolean type (like an integer) as an if condition in Rust?
Rust throws a compile-time error because it does not automatically convert non-boolean types to booleans. No truthy or false values in Rust.
88
In Rust, how must you write a condition to check if a number is not zero?
You must be explicit using a boolean comparison, such as if number != 0 { ... }.
89
How does Rust's approach to memory differ from languages like C (explicit management)?
In Rust, the compiler manages memory through ownership rules, whereas in C, the programmer must explicitly allocate and free memory.
90
What is the runtime cost of Rust's ownership system?
Zero; ownership features do not slow down a program while it is running because they are checked at compile time.
91
What are the two main benefits of mastering the ownership system?
It allows the programmer to naturally develop code that is both safe and efficient.
92
What type of data must be stored on the stack in Rust?
Data with a known, fixed size at compile time.
93
Where is data stored if its size is unknown at compile time?
On the heap.
94
How does dynamic memory allocation work on the Heap?
The allocator (memory manager) searches the heap for a contiguous block of free bytes large enough to satisfy the request. It then marks that block as allocated in its tracking structure and returns the memory address (pointer) of the first byte to the program.
95
How does Rust store types with a known, fixed size at compile time, such as integers or booleans?
Both the owner variable and the value itself are stored entirely on the stack.
96
For dynamic types like String, how is memory distributed between the stack and the heap?
The metadata (pointer, length, capacity) is stored on the stack, while the actual content resides on the heap.
97
What happens in Rust when you assign one integer variable to another (e.g., let y = x;)?
Rust performs a bitwise copy of the value; both variables remain valid because integers are fixed-size Copy types stored on the stack.
98
What happens to the original variable when you assign a heap-allocated type, like a String, to a new variable?
The ownership is moved to the new variable, and the original variable is immediately invalidated to prevent "double free" memory errors.
99
When a String is "moved" from variable s1 to s2, what specific data is copied?
Only the stack data (the pointer, length, and capacity) is copied; the actual heap content is not duplicated.
100
What is the effect of passing a heap-allocated String as an argument to a function?
Ownership of the String is moved into the function, making the original variable in the calling code invalid and unusable.
101
Where is the data for a string literal (e.g., let s = "hello";) stored, and how does it differ from a String type?
It is hardcoded into the program binary (static memory); the variable holds a reference to that memory rather than owning a spot on the heap.
102
What is RAII (Resource Acquisition Is Initialization), and how does it relate to Rust?
A pattern where a resource's lifecycle is tied to a variable's lifetime; in Rust, this is implemented via the drop function.
103
When assigning a String from s1 to s2, what three pieces of data are copied onto the stack?
The pointer to the heap, the length, and the capacity.
104
Why does Rust invalidate the original variable (e.g., s1) after moving its data to a new variable (s2)?
To prevent a double free error, where both variables would attempt to deallocate the same heap memory when they go out of scope.
105
What is the difference between a Move and a Shallow Copy in Rust?
Both copy the stack-based pointer/metadata, but a Move also invalidates the original variable to ensure memory safety.
106
How can you perform a Deep Copy of a String's heap data instead of just moving its ownership?
By calling the .clone() method explicitly.
107
What determines whether a type is Trivially Copied (stays valid after assignment) or Moved?
Types that implement the Copy trait (like integers or booleans) are copied; types that implement the Drop trait (like String) are moved.
108
What is the Copy trait in Rust, and how does it affect variable assignment?
An annotation for types stored entirely on the stack; it allows a variable to remain valid after its value is assigned to another variable because the data is trivially duplicated.
109
Under what condition is a type forbidden from implementing the Copy trait?
If the type (or any of its components) implements the Drop trait, meaning it requires special cleanup logic when it goes out of scope.
110
In Rust, what is a reference, and how does it relate to ownership?
A reference is an address that allows you to access data owned by another variable without taking ownership of it.
111
What is the primary difference between a reference and a raw pointer in Rust?
A reference is guaranteed to point to a valid value of a specific type for its entire duration.
112
What symbol is used in Rust to create a reference to a variable?
The ampersand (&).
113
When a function parameter is defined as a reference (e.g., s: &String), what happens when the function ends?
The reference goes out of scope, but since it didn't own the data, the original value is not dropped.
114
What is the "Big Rule" regarding the number of mutable references you can have for a piece of data at one time?
You can have exactly one mutable reference to a particular piece of data in a particular scope.
115
Why does Rust restrict you to only one mutable reference at a time?
To prevent data races at compile time, ensuring that no two pointers are trying to access and modify the same memory simultaneously.
116
What is the benefit of Rust's strict borrowing rules regarding multiple references?
It allows the compiler to guarantee memory safety and eliminate data races without the need for a runtime garbage collector.
117
Can a mutable reference (&mut) exist at the same time as immutable references (&) to the same value?
No; Rust prevents this to ensure that the data remains constant and predictable for anyone holding an immutable reference.
118
How does the Rust compiler prevent dangling references?
The compiler ensures that the data being referenced will not go out of scope before the reference itself does.
119
According to idiomatic Rust standards, when should a function take ownership of its arguments?
Only when the function specifically needs to own that data; otherwise, it should borrow the data using a reference.
120
In Rust's range syntax (..), how do you represent a slice that starts at index 0?
You can omit the starting value (e.g., &s[..2] is the same as &s[0..2]).
121
How do you represent a slice that includes everything from a specific index to the end of the string?
You can omit the trailing value (e.g., &s[3..] is the same as &s[3..len]).
122
What is the shorthand syntax to take a slice of an entire string?
You can drop both values, using the syntax &s[..].
123
What are the three components of a String "smart pointer" on the stack?
A pointer to the heap data, a length, and a capacity.
124
What are the two components of a String Slice (&str)?
A pointer to a specific starting address and a length of the range.
125
Does creating a slice like &s[0..i] copy the underlying data on the heap?
No; it only creates a new pointer and length on the stack that refers to the existing data.
126
What Rust feature allows a String to be treated as a slice (using &s[..])?
Deref Coercion (made possible because String implements the Deref trait).
127
How do structs differ from tuples in terms of data access?
Structs use named fields, allowing you to access data by name (e.g., user.email) rather than by order or index.
128
In Rust, can you mark only specific fields of a struct as mutable?
No; the entire instance must be declared as mutable (let mut) for any of its fields to be changeable.
129
What does the struct update syntax (..) do?
It allows you to create a new instance of a struct using the remaining values from an existing instance.
130
What happens to the original struct when you use struct update syntax with fields that don't implement the Copy trait?
The original struct is invalidated because the data (like a String) is moved into the new instance.
131
What is a tuple struct?
A struct that has a name but no named fields, accessed via indices like a tuple (e.g., struct Color(i32, i32, i32);).
132
What is a unit-like struct, and when is it useful?
A struct with no fields (struct ExampleStruct;), used when you need to implement a trait on a type but don't need to store any data.
133
Why is it common to use String instead of &str in a basic struct definition?
Using String ensures the struct owns its data, avoiding the need for complex "lifetime specifiers" to keep references valid.
134
Why doesn't Rust provide a default Display implementation for structs?
Structs are complex and ambiguous; Rust doesn't want to guess whether you want to include field names, commas, or specific formatting for the end user.
135
What happens if you try to print a struct using the standard {} placeholder in println!?
It will result in a compile-time error because the struct does not implement the Display trait by default.
136
How do you enable a struct to be printed for debugging purposes?
Add the #[derive(Debug)] attribute immediately before the struct definition.
137
What is the difference between {:?} and {:#?} in debug formatting?
{:?} prints the data on a single line, while {:#?} ("pretty-print") adds newlines and indentation for better readability.
138
How does the dbg! macro differ from println! regarding ownership?
dbg! takes ownership of the expression it evaluates (and returns it), while println! typically takes a reference.
139
Besides the value of the expression, what extra information does the dbg! macro output?
It prints the file name and line number where the macro was called.
140
How does Rust separate data definitions from logic/methods?
Data is defined in a struct, while methods and functions are defined in one or more impl (implementation) blocks associated with that type.
141
What is the difference between an Associated Function and a Method?
Both are in an impl block, but methods take self as their first parameter (equivalent to this), while associated functions do not and are called via Type::func().
142
What does &self represent in a method signature, and how does it relate to TypeScript's this?
It is shorthand for self: &Self. It allows the method to borrow the instance immutably, similar to reading properties of this without being able to modify them.
143
When would you use self (taking ownership) instead of &self (borrowing) in a method?
When the method needs to transform or consume the instance, preventing the caller from using the original object afterward (rare, but powerful for state machines).
144
How does Rust handle the C++ distinction between . (object) and -> (pointer) for method calls?
Rust uses automatic referencing and dereferencing; it automatically adds &, &mut, or * to make the caller match the method signature, so you always just use ..
145
How do you define a Constructor in Rust?
You create an associated function (usually named new) that returns an instance of the type (Self) and call it using the :: namespace syntax (e.g., String::from()).
146
Can a Rust struct have a method and a field with the exact same name?
Yes; Rust distinguishes them by the presence of parentheses. rect.width accesses the field, while rect.width() calls the method.
147
Does Rust automatically generate Getters/Setters like C# properties?
No; you must manually implement them. This is often used to make a field private in a module but provide a public read-only method.
148
Why might a developer use multiple impl blocks for a single struct?
While often grouped together, multiple blocks are useful for organization or when implementing specific Traits (interfaces) and generic constraints.
149
How do you namespace (access) a specific variant of an enum in Rust?
You use the enum identifier followed by a double colon and the variant name (e.g., IpAddrKind::V4).
150
Can Rust enum variants hold data?
Yes, you can put data directly into each enum variant (e.g., strings, numeric types, or even structs), and different variants can hold different types and amounts of data.
151
If you define an enum variant Write(String), what does that variant name effectively become?
It becomes a constructor function that takes a String argument and returns an instance of the enum type.
152
How do you define methods on an enum in Rust?
You use an impl block associated with the enum's name, similar to how methods are defined on structs.
153
What is the purpose of the standard library's Option enum?
It encodes the scenario where a value could be something or it could be nothing, providing a type-safe alternative to "null" values found in other languages.
154
What are the two variants of the Option enum?
Some(T) (which holds a value) and None (which indicates no value is present).
155
Why does Rust use Option instead of null?
To prevent errors where a null value is used as if it were a not-null value. Because Option and T are different types, the compiler forces you to handle the case where the value might be missing.
156
Do you need to explicitly import Option, Some, or None in Rust?
No, the Option enum and its variants are included in the prelude, meaning they are automatically available in every scope.
157
Why does the code let x: i8 = 5; let y: Option = Some(5); let sum = x + y; fail to compile?
Because i8 and Option are different types. You must convert the Option to a T (handle the potential null) before performing operations with it.
158
In the context of Rust's design, what is the "Billion Dollar Mistake"?
It refers to the invention of the null reference, which has led to innumerable errors and vulnerabilities because it is easy to use a null value when a valid value is expected.
159
What is the primary function of the match control flow construct in Rust?
It compares a value against a series of patterns and executes the code block associated with the first pattern that matches.
160
How does the condition in a match expression differ from an if expression?
An if condition must evaluate to a Boolean value, whereas a match expression can be used with any type (such as an Enum or integer).
161
What are the two components of a match arm?
A pattern to match against and the code to run if the match is successful, separated by the => operator.
162
In a match expression, what happens if multiple patterns could theoretically fit the value?
Rust executes the code for the first pattern that matches and then exits the match expression; it does not check subsequent arms.
163
How can you execute multiple lines of code within a single match arm?
You must enclose the lines of code in curly brackets {}, in which case the comma following the arm is optional.
164
How do you extract inner data from an enum variant using match?
You define a variable name within the pattern (e.g., Coin::Quarter(state)), which "binds" to the inner value so it can be used in the arm's code.
165
What does it mean that match expressions in Rust are "exhaustive"?
It means the compiler ensures that every possible value of the type being matched is handled by at least one arm. The code will not compile if any possibility is missed.
166
What is the difference between using a named variable (like other) and the _ placeholder as a catch-all pattern?
A named variable matches any value and binds it so you can use it, while the _ placeholder matches any value but ignores it (does not bind).
167
How do you explicitly tell a match arm to "do nothing"?
You use the unit value () (an empty tuple) as the code execution for that arm.
168
Why is the order of arms important when using a catch-all pattern (like _ or a variable)?
Because patterns are evaluated in order, a catch-all pattern must be placed last. If placed earlier, it would match everything immediately, preventing subsequent arms from ever running.
169
What is the primary purpose of the if let syntax in Rust?
It combines if and let to handle values that match a single specific pattern while ignoring all other patterns, reducing the boilerplate required by a match expression.
170
What is the main trade-off when choosing if let over match?
You gain conciseness (less typing and indentation) but lose the exhaustive checking that match enforces (the compiler won't warn you if you miss a case).
171
How can you conceptually define if let in relation to match?
It is syntax sugar for a match expression that runs code when the value matches one specific pattern and then uses a catch-all pattern (_ => ()) to ignore everything else.
172
How does the variable binding scope differ between if let and let...else?
In if let, the variable is bound only inside the if block. In let...else, the variable is bound in the outer scope (the current scope) if the pattern matches.
173
What is the strict requirement for the else block in a let...else statement?
The else block must diverge; it must return, break, or panic and cannot allow control flow to continue to the code immediately following the let...else statement.
174
Why is let...else considered useful for keeping code on the "happy path"?
It allows you to handle error cases or non-matching patterns early (in the else block) and exit, leaving the main logic and variables available in the top-level scope without deep nesting/indentation.