Iterator vs IntoIterator & cfg
Today I split my time between the iterators video and my CLI project.
I also refreshed the difference between Iterator and IntoIterator.
In yesterday’s journal I got a bit into the Iterator trait. Well, IntoIterator is a trait that implies that something can be converted into an Iterator.
For example, Vec<T> itself is not an iterator. But since it implements IntoIterator, it can be converted into an Iterator.
let v = vec![1, 2, 3];
let iter = v.into_iter();
assert_eq!(Some(1), iter.next());
assert_eq!(Some(2), iter.next());
assert_eq!(Some(3), iter.next());
assert_eq!(None, iter.next()); In the video, there’s also an interesting comparison between different kinds of loops:
fn main() {
let vs = vec![1, 2, 3];
for v in vs {
// consumes vs, owned v
}
for v in vs.iter() {
// borrows vs, & to v
}
for v in &vs {
// equivalent to vs.iter()
}
} Luckily, the compiler will help us to choose the correct one, but it is fundamental to know our fundamentals :)
Cfg
Today I also learned about cfg: https://doc.rust-lang.org/rust-by-example/attribute/cfg.html
This came by from working on my CLI project. I know from experience that it’s the best way to learn.
This CLI project I’m doing is a Pomodoro timer. I want to play a notification sound, so I’m using rodio.
There was a useful log message that appeared constantly. Checking the docs, there is a way to eliminate it. And I thought: how can I have it on my development but not in the released version?
And there was the answer: the cfg attribute and macro. With cfg, you can conditionally run code and booleans depending on many factors: https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute
I ended up doing:
sink_handle.log_on_drop(cfg!(debug_assertions)); Where cfg! is a macro that returns a boolean, and debug_assertions will differentiate between development and production: https://doc.rust-lang.org/reference/conditional-compilation.html#debug_assertions