Crust of Rust: Iterators

Поділитися
Вставка
  • Опубліковано 20 січ 2025

КОМЕНТАРІ • 94

  • @howardmarles2576
    @howardmarles2576 4 роки тому +163

    As a Rust beginner, I find your videos invaluable. Thank you Jon !!

    • @artgreg2296
      @artgreg2296 4 роки тому +16

      i exactly think the same. its crazy this is free content

    • @dude2542
      @dude2542 3 місяці тому

      Update on your expertise?

  • @connormatza5873
    @connormatza5873 3 місяці тому +1

    this is the best rust content produced, ever. Most rust devs or wannabes have programmed a computer before so will quickly get tired of "from zero" tutorials

  • @vroomerlifts
    @vroomerlifts 2 роки тому +3

    I just learnt iterator design pattern and now this, was super relatable.

  • @jeremycoleman3282
    @jeremycoleman3282 4 роки тому +28

    I love that your inclination is to show the correct use first. So many programmers preface their guides with the wrong way first and it makes me rage

    • @theninjascientist689
      @theninjascientist689 Рік тому +1

      it puts me on edge when I hear "so we could do it like this..." in a programming tutorial. I then have no idea if it's a valid alternative or just plain wrong until I watch the rest of the video

    • @VHenrik007
      @VHenrik007 Місяць тому

      I think understanding what is wrong with a wrong example can be just as important and insightful as knowing how to properly do something when it comes to understanding certain concepts. The process of showcasing a wrong example often times makes it more memorable. A problem is posed -> you ponder, and then see a seemingly good solution -> turns out that solution has a key issue -> memorable facepalm -> now comes the proper solution, and you can actually understand why that is a proper solution. At least for me, this process is often times best, because next time I encounter the same problem I can easily remember what went wrong last time, instead of having to remember the exact solution itself.

  • @Mahmudul_Hasan92
    @Mahmudul_Hasan92 Рік тому +4

    I am learning so much from you. Working with rust code from your streams and going from (kind of getting it) to (okay I actually GET it) feels oddly satisfying, and I have never felt like this while learning other languages over the years.

  • @jackmead7292
    @jackmead7292 4 роки тому +25

    I am so, so, so tired of writing javascript and python. The most complicated thing I do all day is refactor crapping javascript formatting and try to convince people to follow better eslint rules, learn yet another annoying new npm package that probably has way to many dependencies, or have to constantly keep CTRL-F 'ing through a crappy python function that is 100 lines long. I am ready for Rust. Let's go!!
    Great video. Great explanation. Thank you so much 🙏

    • @vorname1485
      @vorname1485 4 роки тому +11

      I use typescript in fully strict mode, when I have to work with javascript.

  • @fredrikjonsen6222
    @fredrikjonsen6222 4 роки тому +19

    Really enjoying these Crust of Rust videos. The more lengthy videos are interesting, but I often feel lost halfway through. The shorter ones feel more relevant when you're still learning the basics but have gotten through the book.

  • @jonas-mm7em
    @jonas-mm7em 3 роки тому +10

    Thank you Jon for all these learning materials. This is definitely helpful. I'm going through the whole crust of rust series and then I'll go through your book as well. I already book the pre-release. 💪😁

  • @vorname1485
    @vorname1485 4 роки тому +36

    10:00 into_iter takes the ownership of the value, which is the meaning of "into", the ownership is transfered "into" the iterator. value.into_iter() makes sense this way :)

    • @vorname1485
      @vorname1485 4 роки тому +3

      @@YuruCampSupermacy correct :)

    • @jonhoo
      @jonhoo  4 роки тому +11

      Yup, that's all correct. Keep in mind as I show later on though that `iter` is an inherent method, while `into_iter` is a trait method from the `IntoIterator` trait. Which means that other types and methods can be generic over it. This is why you'll still want to implement `IntoIterator` for, say, `&Vec` (which would effectively do the same as `Vec::iter`)

    •  4 роки тому +8

      > into_iter takes the ownership of the value, which is the meaning of "into", the ownership is transfered "into" the iterator
      True, though I want to point out something that had me confused for a long time, in case it helps somebody else: `into_iter` taking ownership initially led me to think that it always consumes the underlying collection. That's not necessarily the case though, because that "value" can be a reference, in which case `into_iter` takes ownership of a reference (a.k.a. precious little). E.g. there's an impl of `IntoIterator` for `&Vec`: doc.rust-lang.org/src/alloc/vec.rs.html#1971-1978 (which basically just defers to `Vec::iter`, as Jon says).
      Here's a playground with a bit of code that helped me clear up that confusion: play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4a6c2e0230d98237e7ad86d239db4655
      (I'm only part way through watching the video -- which is great as always, thanks! -- so apologies if this is addressed somewhere in there :) Still, hopefully someone might find it useful to have this information in the comments as well.)

    • @luiswirth
      @luiswirth 4 роки тому +4

      @ Thanks David, now I get it!

    • @starczarar
      @starczarar 10 місяців тому

      I agree, the author didn't know this. "It’s easier to type" was his guess.

  • @KiffinGish
    @KiffinGish 4 роки тому +4

    Perfect presentation, I look forward to following your series as more presentations are made!

  • @wvanmourik1
    @wvanmourik1 4 роки тому +2

    Thank you so much for these series. Really happy to see these type of videos about advanced Rust topics.

  • @abdulazizalabodi
    @abdulazizalabodi 4 роки тому +3

    Thank you for the video! I have used iterators in other languages such as java and I am fairly familiar with the concept. But I still found your explanation useful.

  • @Tantandev
    @Tantandev 4 роки тому +6

    Thank you for these videos! Very helpfull!

  • @unspecifiedsender9035
    @unspecifiedsender9035 2 роки тому

    This is the next rust video I've watched

  • @damickillah
    @damickillah Рік тому

    76K views should equal 76K likes. The value in this man's content is incomprehensible, in my opinion(s).

    • @RajaKhan-dc4vs
      @RajaKhan-dc4vs 6 місяців тому +1

      true, I recently have started to explore his playlists. he is next level programmer. He is bringing so much value , low level understanding of iterator, macros and other stuffs which we can use to rewrite the industry level framework stacks from scratch in rust itself. although i am keeping the hype aside. but the core rust is immense valuable and future .

  • @NoNameAtAll2
    @NoNameAtAll2 3 роки тому +2

    9:58 iter and into_iter are 2 different things, aren't they? Iter is "read-only access" and into_iter is "consuming access"
    In what way do they do same thing?

    • @rurunosep
      @rurunosep 2 роки тому

      I think the idea is that a.iter() is effectively just an alias for &a.into_iter(), and a.iter_mut() is also effectively just an alias for &mut a.into_iter(). into_iter() will give "read-only access", "mutating access", or "consuming access" depending on the context. You could also think of it as consuming the references when called with a reference. iter() and iter_mut() are redundant but convenient.

  • @brod515
    @brod515 Рік тому +1

    I'm leaning rust but... but one things I've started to notice (especially in this video ) is how crucial testing is and how rust makes it easy to encourage you to write them...

  • @velimirchakhnovski2380
    @velimirchakhnovski2380 9 місяців тому +1

    I'm still about halfway through the video (44:50), and it seems we finished talking about flatten, but can't it be improved?
    I don't see why it would need an Option for the inner iterator.
    We could have new like this:
    ```
    let inner = iter.next();
    Flatten { outer: iter, inner }
    ```
    and next like this:
    ```
    loop {
    if let Some(elem) = self.inner.next()
    return Some(elem);
    self.inner = self.outer.next()?;
    }
    ```
    This seems more elegant than the implementation of next that's shown in the video.

    • @velimirchakhnovski2380
      @velimirchakhnovski2380 9 місяців тому

      I can see that this wouldn't work for DoubleEndedIterator. We would need to call next_back in new, and so our Flatten wouldn't accept iterators that don't implement DoubleEndedIterator.
      Although it seems to me that Flatten and DoubleEndedFlatten should have been two types anyways, given that they don't need the same fields...
      Maybe in practice it's better to have one type for both use cases, but I'm not experienced enough to judge when that might be the case.

  • @ramazangCoder
    @ramazangCoder 2 місяці тому

    omg! That is crazy man! Jeg elsker det

  • @TON-vz3pe
    @TON-vz3pe 9 місяців тому

    How does flatten even call thr next() method in the iterator? All I see in code is a new() and getting a Flatten instance

  • @AryungChen
    @AryungChen Рік тому +3

    It's so great about how to think and try to implement by self to learn. By the way, is there any vim/nvim config in the video? It is good to have such lint related info or error show up. Thanks

  • @kurjak9595
    @kurjak9595 4 роки тому +4

    Hey, can you put together a stream for the topic Smart pointers? I personally read the book about 2-3 times and still don't get the Cell and RefCell pointers.

  • @user-ov5nd1fb7s
    @user-ov5nd1fb7s 4 роки тому +1

    Great videos, thanks.

  • @niklashalonen9296
    @niklashalonen9296 4 роки тому

    At 42:00 you didn't remove `self.inner = None` from line 43. The tests pass without the line just fine. What is the reason for leaving it in?

    • @jonhoo
      @jonhoo  4 роки тому +1

      It works fine because the inner iterator also keeps track of the fact that it's been exhausted. So next time around, we'll enter the outer `if let`, but the call to `next()` will yield `None`, and so we'll fall down to the code below again. But that means we're now relying on it being okay to call `next()` on the inner iterator after it has returned None, which is not the case for all iterators!

  • @kostareg
    @kostareg 3 роки тому +1

    39:00 couldn't you just call inner_iter.into_iter().next() instead of doing all of that work with trait bounds?

  • @xrafter
    @xrafter 3 роки тому

    Why does &[T] slices implement iterator but normal arrays don't ?
    Edit: from rust 1.54 the array primitive implement the iterator trait

    • @jonhoo
      @jonhoo  3 роки тому +1

      Take a look at blog.rust-lang.org/2021/05/11/edition-2021.html#intoiterator-for-arrays, which gives a lot of context for that particular nuance.

  • @veetaha
    @veetaha 4 роки тому +2

    It would be cool to upload the streams as full-fledged YT streams such that the chat is also recorded and we can see it after the fact, but I am not sure if it is possible to cut the intro bootstrap part...

    • @jonhoo
      @jonhoo  4 роки тому +3

      The live stream version with the comments is already linked at the bottom of the description :)

  • @DavideVegliante
    @DavideVegliante 3 роки тому

    Thank you! This is great

  • @haphamdev
    @haphamdev 3 роки тому

    Thank you very much for this nice series. Could you read the questions from comments slowly so that we can hear them?

  • @jeffg4686
    @jeffg4686 4 роки тому

    Can anyone say if an Associated Type basically just a typedef nested into a type, or is there more to it than that? Sounded like a new concept or something when first learning rust, and some compare to generics, but it's hard-coded to some type (which may or may not be a generic type). But a direct comparison to generics doesn't really seem to make sense to me at all - even if the type being defined leverages generics. Associated type is just a nested typedef, or I am actually way off here?

    • @jonhoo
      @jonhoo  4 роки тому +2

      Hi Jeff! An associated type is sort of like a nested typedef, but it is nested not per type, but per implementation of a trait. For example, if some type Foo implements the trait Bar twice for two different Ts, it can use different types for an associated type of Bar for those two impls. Associated types can also have trait bounds, and can be referenced elsewhere in the trait. For example, the Deref trait from the standard library has an associated type Target, and a method fn deref(&self) -> &Self::Target.

    • @jeffg4686
      @jeffg4686 4 роки тому

      @@jonhoo - great answer, thanks

  • @Singlton
    @Singlton 6 місяців тому

    what about implementing the iter() trait for a LinkedList , its so hard !!!

  • @ksleo2328
    @ksleo2328 3 роки тому

    This video has no subtitles, could anyone explain why?

  • @adicide9070
    @adicide9070 Рік тому

    peeps, what is this font used here in vim? anyone know?

    • @well.8395
      @well.8395 Рік тому

      I think Monolisa.

    • @adicide9070
      @adicide9070 Рік тому

      @@well.8395 noto sans mono, actually. said in the q&a for july 23 today.

  • @Yotanido
    @Yotanido 3 роки тому +3

    I don't know if it's a conscious choice or you don't know about it, but coc offers rename refactoring with (coc-rename)
    I noticed you do a lot of manual renaming, so I thought I'd point it out. I've personally got it mapped to F3

  • @darthmoomoo
    @darthmoomoo 3 роки тому

    With the extension trait, will deep() work without "flatten(flatten" ? Your unit test only goes to two levels.

  • @jeffg4686
    @jeffg4686 4 роки тому

    I find it interesting that they choose to use & when denoting a parameter must be borrowed (ref), but for patterns they use the 'ref' keyword. That tripped me up when I was first learning rust. Any thoughts on why they chose to spell it out in patterns (maybe just to indicate it's a pattern) ?

    • @jonhoo
      @jonhoo  4 роки тому +2

      The two are actually not the same. They're more like opposites. A &foo in a pattern is "match foo as what's behind the reference", whereas ref foo is "match foo as a reference".

    • @jeffg4686
      @jeffg4686 4 роки тому

      @@jonhoo - ah gotcha, definitely big difference there. much thanks

  • @georgespringbach2062
    @georgespringbach2062 4 роки тому +1

    Rust is cool! U are cool 😎 too Jon!

  • @danieledepetris4582
    @danieledepetris4582 4 роки тому +1

    Hi Jon thanks for your evangelism on Rust, I have a tip for your videos on UA-cam you should if possible enable English subtitles

    • @jonhoo
      @jonhoo  4 роки тому +1

      They are already enabled, but UA-cam unfortunately isn't great about adding automatic captions for longer videos. Community captions are enabled though if someone feels a calling!

  • @johnbotris8187
    @johnbotris8187 4 роки тому

    I'm not sure if this gets answered later on or if I missed something, but regarding the Flatten implementation: is there a particular reason why O is bounded to Iterator, but O::Item is bounded to into Iterator? why not the other way round or have them both be the same?

    • @jonhoo
      @jonhoo  4 роки тому

      I don't know if this became clearer throughout the stream, but the answer is that the outer iterator has to be Iterator because we store the outer iterator itself directly in the struct (if it was IntoIterator, and we stored a O::IntoIter, I _think_ the compiler would complain). We also don't _need_ the Into part of IntoIterator in Flatten, so why make the bound larger than it needs to be? For the inner iterator however, we _are_ going to turn each element of the outer iterator _into_ an Iterator, so we need it to implement IntoIterator. If it just implemented Iterator, then we'd need to mutate the iterator we're walking over directly!

  • @uoweme5grand
    @uoweme5grand 2 роки тому

    Holy crap there is a person behind you. I did not see that until the end.

  • @haI9k
    @haI9k 4 роки тому

    And now something completely different ;)
    What is the name of this zsh option/extension which shows suggestion based on history? e.g. 2:38

    • @jonhoo
      @jonhoo  4 роки тому

      I use the fish shell, not zsh, which does this by default :)

  • @metamemelord
    @metamemelord 4 роки тому +2

    That's a pretty nice vim skin, which one is it?

    • @jonhoo
      @jonhoo  4 роки тому +3

      It's called gruvbox-dark-hard :)

  • @_sandeepnambiar
    @_sandeepnambiar 4 роки тому +2

    What is your desktop setup? It looks quite nice!

    • @jonhoo
      @jonhoo  4 роки тому +3

      I actually did a full video on that over at ua-cam.com/video/ycMiMDHopNc/v-deo.html :)

  • @DerH0ns
    @DerH0ns 4 роки тому +1

    Isn't your approach to implementing DoubleEndedIterator wasting a lot of memory in the case where we don't actually use DoubleEndedIterator?

    • @jonhoo
      @jonhoo  4 роки тому +5

      I touch on this towards the end of the video, and why it currently has to be there. You're right that it's wasting a bit of memory, but keep in mind that it's just storing an extra iterator, which is itself unlikely to be very large (a hash map iterator for example is mostly just a couple of pointers). In practice, it's also unlikely to matter much, since it is stack allocated, and iterators are usually short-lived. It is unlikely that you have, say, hundreds of thousands of `Flatten` iterators active at the same time.

  • @michaelflynn6952
    @michaelflynn6952 2 роки тому

    I feel like every topic you introduced you just said "but this isnt what we're here to talk about" or "but that isn't important right now" and it left me wondering what IS being demonstrated

  • @mavichovizana5460
    @mavichovizana5460 3 роки тому

    I think the reason that `O::item::item` could not compile is because O::item could be associated constant. This is same with C++, where you need to use `typename` to tell the compiler that `item` is a type not a value.

  • @shironbenyamini2798
    @shironbenyamini2798 4 роки тому

    Not sure I understand the purpose of associated types and why not use generics. If all they're for is as you said, to make life easier for the compiler and maybe shave off a second of compile time, why not just use generics and be done with it? surely there's more to it then that? I can't imagine the core team introduced this language "construct" just for that? Does it provide additional benefits?

    • @jonhoo
      @jonhoo  4 роки тому

      As I alluded to in the video, they enable you to constrain implementation of the trait to only a single instance per type, which can often times be necessary to get type inference to work. Associated types also tend to be more ergonomic to use, precisely because they're more constrained. Take the Future trait for example - you don't need to specify the Output type every time you take a F: Future, because the Output type is associated, and thus dictated by F.

  • @SeniorMarsTries
    @SeniorMarsTries 3 роки тому

    What is that drawing program?

    • @jonhoo
      @jonhoo  3 роки тому

      It's called MyPaint :)

  • @trolledwoods377
    @trolledwoods377 4 роки тому +1

    Jo(h)n gang!!!

  • @user-ov5nd1fb7s
    @user-ov5nd1fb7s 4 роки тому

    On a side note, I think you hold the Guinness world record for saying iterator a gazillion times in an hour.

    • @meuko
      @meuko 4 роки тому

      I wonder if this being a video about... iterators had any part in that.

    • @user-ov5nd1fb7s
      @user-ov5nd1fb7s 4 роки тому

      @@meuko it was a joke man....jeez

    • @meuko
      @meuko 4 роки тому

      @@user-ov5nd1fb7s Hey dude I was also joking, sorry

  • @sayakchatterjee4454
    @sayakchatterjee4454 4 роки тому +16

    I just realized that even after trying to learn Rust for over a year, I still don't understand so much of the basics. 😭

    • @jonathanguillotte-blouin4327
      @jonathanguillotte-blouin4327 4 роки тому +23

      Have you tried to write something in Rust? If not, I would recommend to do so! As many things in life, you can only get better by practicing. :)

  • @Dygear
    @Dygear 2 роки тому

    I have the feeling that your local IP address 10.0.1.27 is a play on 127.0.0.1.

  • @rzlink001
    @rzlink001 2 місяці тому

    Looks like someone is playing video game in the couch.

  • @mcpecommander5327
    @mcpecommander5327 Рік тому

    I don’t think your explanation of .iter vs .into_iter is correct. .into_iter is a trait method that consumes the value, and generally gives an iterator that gives the values in the collection by-value. .iter is a naming convention for a method that takes the collection by-reference and returns an iterator that iterates also by-reference. Also, slice ([T]) does not implement IntoIterator, while &[T] does (which is also common for types that can be .iter-ed to have references to them implement IntoIterator)

  • @syphiliticpangloss
    @syphiliticpangloss 2 роки тому

    Over some explaining concepts. Too little on syntax craziness.

  • @usercommon1
    @usercommon1 9 місяців тому

    I fell asleep while watching this video😭

  • @well.8395
    @well.8395 Рік тому

    I like your videos Jon, but can you avoid doing Tsskk sound every minute or so. It's very irritating to me someone suffering from misophonia. Thank you very much for the content 👍