Rust Interior Mutability - Sneaking By The Borrow Checker

แชร์
ฝัง
  • เผยแพร่เมื่อ 19 ม.ค. 2023
  • The limitations of the Rust borrow checker and how to work around them with interior mutability. Cell, RefCell, RwLock and Mutex are all covered.
    -
    Stuff I use to make these videos:
    Camera: Canon EOS R5 amzn.to/3CCrxzl
    Monitor: Dell U4914DW 49in amzn.to/3MJV1jx
    Keyboard: Keychron Q1 amzn.to/3YkJNrB
    SSD for Video Editing: VectoTech Rapid 8TB amzn.to/3hXz9TM
    Microphone 1: Rode NT1-A amzn.to/3vWM4gL
    Microphone 2: Seinheiser 416 amzn.to/3Fkti60
    Microphone Interface: Focusrite Clarett+ 2Pre amzn.to/3J5dy7S
    Tripod: JOBY GorillaPod 5K amzn.to/3JaPxMA
    Mouse: Razer DeathAdder amzn.to/3J9fYCf
    Computer: 2021 Macbook Pro amzn.to/3J7FXtW
    Lens: Canon RF24mm F1.8 Macro is STM Lens amzn.to/3UUs1bB
    Caffeine: High Brew Cold Brew Coffee amzn.to/3hXyx0q
    More Caffeine: Monster Energy Juice, Pipeline Punch amzn.to/3Czmfox
    Building A Second Brain book: amzn.to/3cIShWf
  • วิทยาศาสตร์และเทคโนโลยี

ความคิดเห็น • 240

  • @AzureFlash
    @AzureFlash ปีที่แล้ว +329

    New in Rust 1.69: the Vibe Checker

    • @dj-maxus
      @dj-maxus ปีที่แล้ว +25

      nice

    • @guilherme5094
      @guilherme5094 ปีที่แล้ว +19

      Nice.

    • @Khusyasy
      @Khusyasy ปีที่แล้ว +17

      Nice.

    • @ThePrician
      @ThePrician ปีที่แล้ว +11

      Nice.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +29

      somebody might have to walk me through this one... 🤓

  • @andrewdunbar828
    @andrewdunbar828 ปีที่แล้ว +105

    I would love to watch some in-depth analysis on what currently is not feasible for a borrow-checker to accept but that is memory safe. A breakdown of various types of situations, which are likely to be fixable sooner, which later, and which perhaps never.

  • @user-ur8mn6po5n
    @user-ur8mn6po5n ปีที่แล้ว +38

    I encountered some these before but had trouble following the differences between them and I didn't get why I would use one over another, now that I've heard them all explained at once it makes much more sense. Thanks!

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +2

      nice, glad you found this approach valuable!

  • @bamgoesn
    @bamgoesn 4 หลายเดือนก่อน +5

    ngl this video is a much better introduction to interior mutability than the rust book

  • @Christobanistan
    @Christobanistan 4 วันที่ผ่านมา

    By far the best explanation I've found, and the only one I've understood!

  • @TheRealBrenny
    @TheRealBrenny ปีที่แล้ว +4

    Because I'll keep coming back to this, here are some timestamps (please pin this!):
    0:00 - Intro
    1:31 - The Problem
    5:34 - Cell (Cloning Available)
    8:00 - RefCell (No Cloning)
    10:37 - RwLock (Multithreading R/W Locks)
    14:34 - Mutex (Multithreading Single Lock)
    15:46 - Outro

  • @IqweoR
    @IqweoR ปีที่แล้ว +5

    This is what I needed to try and implement the Monte Carlo tree search in Rust, thank you so much for the clear explanation

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      nice, glad you found it valuable!

  • @virusblitz
    @virusblitz 10 หลายเดือนก่อน +2

    You are so good at explaining these! Your rust content is the best out there!

    • @codetothemoon
      @codetothemoon  10 หลายเดือนก่อน +2

      thank you for the kind words, really happy it's been valuable to you! 😎

  • @poketopa1234
    @poketopa1234 2 หลายเดือนก่อน +2

    Clearest explanation I've seen so far. Would have taken 2 minutes to write in c++

    • @codetothemoon
      @codetothemoon  หลายเดือนก่อน +1

      thanks! yes the example given in this video would probably be easier to write in pretty much all other mainstream languages. it can be seen as an example of the extra burden placed on the developer in exchange for Rust's performance and safety

  • @RobertKing
    @RobertKing หลายเดือนก่อน

    Great video thanks. Haven't used RwLock much before so good to know about it

  • @HadiAriakia
    @HadiAriakia 9 หลายเดือนก่อน +1

    Thanks a lot. Really appreciate your high quality videos

    • @codetothemoon
      @codetothemoon  9 หลายเดือนก่อน +1

      thanks for watching, glad you got something out of it!

  • @nirmalyasengupta6883
    @nirmalyasengupta6883 11 หลายเดือนก่อน +1

    Short and sweet. Thank you!

    • @codetothemoon
      @codetothemoon  11 หลายเดือนก่อน

      thanks for watching, really happy you got something out of it!

  • @hupa1a
    @hupa1a ปีที่แล้ว +2

    Wow! This is so informative and easy to follow, although it's a complex topic for beginners like me! Great job

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      thank you, really glad you got something out of it!

  • @MasterHigure
    @MasterHigure ปีที่แล้ว +22

    7:10 I would usually write
    for &adj in &node.adjacent
    or whatever variation makes the borrow checker and type checker happy (the &adj is a pattern match, so you can use just adj both in the for declaration and the function call in the line below if that suits your needs, and I assume clippy will tell you as much).
    That's what I did everywhere in my Advent of Code. That's also what your error message actually recommends.

    • @JosephDalrymple
      @JosephDalrymple ปีที่แล้ว +2

      That's what I initially thought was going to be done, but it's pretty interesting to see the different approaches.

    • @MasterHigure
      @MasterHigure ปีที่แล้ว

      @@JosephDalrymple Sure. I can never really remember which is which of iter() and into_iter() and which one for loops call implicitly, so another repetition will not hurt.

    • @Starwort
      @Starwort ปีที่แล้ว +1

      @@MasterHigure I usually use the knowledge that most 'into' functions are consuming to remember which way round they are; for loops you just kinda have to remember that it's into_iter though

  • @reneribaud8912
    @reneribaud8912 ปีที่แล้ว +4

    I enjoyed this video. I had some trouble understanding Cell and Refcell, and this video is beneficial to clarify these concepts. I think the example you have chosen is excellent because simple enough to focus on the concepts and not be bothered understanding a complex code. The explanations are also really clear, so thanks for sharing this content. That is an excellent job.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      Than you so much, I'm glad you found it valuable! I found these concepts confusing as well, and I tried to make the explanation I wish I had had.

  • @flippert0
    @flippert0 5 หลายเดือนก่อน +1

    Very good and concise intro into that important Rust topic, thanks!

    • @codetothemoon
      @codetothemoon  5 หลายเดือนก่อน

      thanks, really glad you got something out of it!

  • @rancidbeef582
    @rancidbeef582 ปีที่แล้ว +31

    Very helpful video. I've been trying to port a simple simulation "game" with rather complicated data structures to Rust. I generally use this as a test to learn features of a new language. I originally wrote it on my Commodore 64 in BASIC (yes, I'm old, lol), then ported it to 6502 assembly, later C, C++, Java, and Python. Now I'm trying to port it to learn Rust and the borrow checker is giving me hell. I'm on my 6th refactor and I still don't have it working... I think the info from this video may help, though!

    • @rancidbeef582
      @rancidbeef582 ปีที่แล้ว +11

      And I'll say that using Java for the last several years has nearly ruined me for trying something like Rust. Java encourages the use of many aliased references and cleans up the mess for you. I think someone who has only ever done Java and never, say, C or C++ is going to have a hard time grok-ing Rust.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +8

      nice, glad you found it valuable! That's cool that you have the same game that you use as a litmus test for new languages that you learn - what a great way of teasing out the things you like and don't like when you are learning a new language

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +7

      yeah I agree that having a background solely in garbage collected languages will definitely make Rust tougher to pick up...

  • @sparky173j
    @sparky173j ปีที่แล้ว +4

    I realise that you're presenting a general case.
    I've used the Atomic classes for simple types (bool, ints, floats) which are no bigger than my architecture, as they have ideal performance when you call them with relaxed timing.
    When you enable any optimisation, it optimises down to the bare minimal instructions for assigning the data type.

  • @modolief
    @modolief ปีที่แล้ว +3

    Very very nicely done. Kudos.

  • @kiranraaj7889
    @kiranraaj7889 ปีที่แล้ว +1

    Thanks really, explained a lot of concepts I was having trouble with!

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      Great, really happy it was helpful!

  • @mariorossi7930
    @mariorossi7930 ปีที่แล้ว +1

    Wow, very neat explanation! 👍

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      thanks, glad you found it valuable!

  • @alextrotta796
    @alextrotta796 ปีที่แล้ว +5

    Very helpful video! I think this will come in handy with converting some C++ code to Rust, as it might be safe but just harder to express with the borrow checker.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      nice, glad you found it valuable!

  • @Drama-ck2tp
    @Drama-ck2tp ปีที่แล้ว +2

    Going to try to implement some of this info into a doubly linked list , thanks!

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      nice, that is also a great scenario where interior mutability can be leveraged!

  • @austinperrine23
    @austinperrine23 2 หลายเดือนก่อน +1

    This was awesome! Thanks

    • @codetothemoon
      @codetothemoon  หลายเดือนก่อน

      glad you liked it!

  • @Joe-mh9di
    @Joe-mh9di ปีที่แล้ว +2

    Love the thumbnail! Thanks for the video.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      thanks and thanks for watching!

  • @davidwalton7012
    @davidwalton7012 ปีที่แล้ว +1

    Great content, and I like your "no bullshit" style. Subscribed!

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      thanks, very happy to have you onboard!

  • @clo4
    @clo4 ปีที่แล้ว +30

    Nice! I’d also be interested in a crust-of-rust-but-faster style overview of how Cell/RefCell work internally, if there’s any insights to be gained there.

    • @ChristianJacobsen
      @ChristianJacobsen ปีที่แล้ว +8

      Can recommend "Rust Atomics and Locks" by Mara Bos, which covers this exact topic. Available for free on her website.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +6

      I can definitely understand the desire for something like Crust of Rust but that is more concise. This video was actually heavily inspired by Jon Gjengset's coverage of the same smart pointers, in a way that I am hoping was complimentary. He covers the implementation details, so I decided to cover practical usage examples. I'm afraid I don't quite have the expertise to do a video on the implementation details at the moment, but in the meantime I'd highly recommend Jon's video on the topic if you haven't already watched it!

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      nice, going to put this on my list of things to check out!

    • @Dygear
      @Dygear ปีที่แล้ว

      The Crust of Rust, but Faster than Lime? LOL

    • @kiranraaj7889
      @kiranraaj7889 ปีที่แล้ว

      @@codetothemoon i actually wanted to see practical usecases of these smart pointers after jons video and you posted exactly what we all wanted

  • @lMINERl
    @lMINERl ปีที่แล้ว +1

    This vid is gold 🥇

  • @piraka_mistika
    @piraka_mistika 8 หลายเดือนก่อน +1

    This was so helpful!

    • @codetothemoon
      @codetothemoon  8 หลายเดือนก่อน +1

      nice, really happy you got something out of it!

  • @druzzyaka
    @druzzyaka ปีที่แล้ว +1

    Nice explanation, thanks!

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      glad you found it valuable, thanks for watching!

  • @pineiden
    @pineiden 11 หลายเดือนก่อน

    Thanks! Excelent content

  • @paulgross7734
    @paulgross7734 ปีที่แล้ว +1

    Wonderful!

  • @dionysis_
    @dionysis_ ปีที่แล้ว

    Great content 🙂👍

  • @markolsson2740
    @markolsson2740 ปีที่แล้ว +7

    Again, a really great video! Can I request a video about lifetimes, specifically knowing what to add when rust tells you it needs them.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +2

      Thanks so much Mark! If you haven't already, check out the "Rust Demystified" video - the second part is about lifetimes. Though I'm sure there are more, it covers the main concepts and use cases.

    • @markolsson2740
      @markolsson2740 ปีที่แล้ว +3

      @@codetothemoon Thanks, yeah...that helped a little. How about a video on bits and bytes? Using the Bytes crate, [u8] etc...bit shifting...

  • @farbodshahinfar4246
    @farbodshahinfar4246 ปีที่แล้ว +1

    You are awesome !

  • @heret1c385
    @heret1c385 16 วันที่ผ่านมา

    I'm writing a gameboy emulator right now, and the emulator is split up between the different chips in the gameboy, e.g. the cpu, the picture processing unit (ppu) and the audio processing unit (apu). My problem now is, that these chips communicate to each other by writing into a shared memory space, which effectifly is shared mutable state in my emulator. I had some trouble finding elegant solutions. Your video helped me a lot, thanks!

  • @lucccar
    @lucccar ปีที่แล้ว

    How and why Arc is a costless abstraction?

  • @Christopher-dj3uq
    @Christopher-dj3uq ปีที่แล้ว +1

    Great video! Which IDE are you using?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      DOOM emacs, which has been my go-to editor for the past few months github.com/doomemacs/doomemacs

  • @loganhodgsn
    @loganhodgsn 11 หลายเดือนก่อน

    I like using cell for non-copy types too.
    Doing `let mut contained = cell.replace(String::new());` allows you to take the string out of the cell, and it can be put back with `cell.replace(contained);`

  • @jeffg4686
    @jeffg4686 ปีที่แล้ว +2

    If you're looking for topics, I think a nice related topic (regarding graphs) is IndraDB would be a great one. I never really had a need for a graph database yet, but I'm sure I will at some point, and would be cool to know an open source rust graph db.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      Thanks Jeff, I've put it on my list of stuff to check out!

  • @football-is-divine
    @football-is-divine 4 หลายเดือนก่อน

    How do you the change the style of line numbers? Which theme are you using for it ?

  • @filippodegrandi8804
    @filippodegrandi8804 ปีที่แล้ว +1

    Great video as always, I was wondering since I'm rewriting my neovim config from zero, what color scheme is this?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      I'm using doom emacs for this video with the doom-monokai-pro theme - but i'm sure there is a Neovim equivalent.

  • @pineiden
    @pineiden 11 หลายเดือนก่อน

    Can You give an use case of Cow Smart pointer?

  • @vitornesello
    @vitornesello 10 หลายเดือนก่อน +1

    @codetothemoon Great video! And I loved you doom emacs setup, would you mind sharing your dotfiles?

    • @codetothemoon
      @codetothemoon  10 หลายเดือนก่อน +1

      thank you! sure - here they are github.com/MoonKraken/dotfiles/tree/master/.doom.d

    • @vitornesello
      @vitornesello 10 หลายเดือนก่อน

      @@codetothemoon thanks a lot!

  • @meowsqueak
    @meowsqueak 10 หลายเดือนก่อน

    In the end, the Node struct ends up with various smart pointers on different fields. I understand we got there by construction, but I wonder if there’s a way to refactor it so that the smart pointers are just on Nodes, rather than the internal fields? Could the add_urgency() function somehow lock an entire node rather than the internal field? What would that look like?

  • @EbonySeraphim
    @EbonySeraphim 4 หลายเดือนก่อน

    Tried to write a trivial LinkedList in Rust and ran head first into problems when trying to modify the list, and writing methods to modify the list. Felt like I was kinda close but never quite got there….this is definitely what I missed.

  • @BrazenNL
    @BrazenNL หลายเดือนก่อน

    3:24 I'm confused by ` 4 j`. Normally, `` is move up half a screen, but it's not doing that. Have you remapped it?

  • @juan0338
    @juan0338 ปีที่แล้ว

    Would the final lock-based solution work with any generic type for the node payload? Let's say Node was a generic struct. Btw, thanks a lot for the great content!

    • @carlosmspk
      @carlosmspk ปีที่แล้ว +1

      Yes, it would. Including types that are not "Sized" (i.e. whose size is not known at compilation time)

  • @spark_coder
    @spark_coder ปีที่แล้ว +4

    Can you also explain the difference between Rc and Arc?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +9

      Check out my other video, “Rust’s alien data types”, for that explanation 😎

    • @spark_coder
      @spark_coder ปีที่แล้ว +3

      @@codetothemoon 😁 Good plug... But also thank you :)

    • @Chex_Mex
      @Chex_Mex ปีที่แล้ว +5

      @@spark_coder a tldr, RC is reference counting and ARC is *atomic* reference counting. You need atomic instructions in order to use a reference counter across threads, otherwise you would have data races.

    • @spark_coder
      @spark_coder ปีที่แล้ว +3

      @@Chex_Mex oh so kind of like std::atomic in cpp... Cool :)

  • @oconnor663
    @oconnor663 5 หลายเดือนก่อน

    > There's no potential for dangling references...
    That's mooostly true for sure, but you could do it if you really wanted to. Suppose you added some elements to node A's adjacent Vec, and then you went through node B to grab a reference to one of those elements. That would be a &&Node double reference, which is kind of weird, but whatever suppose we grabbed it. Then, if Rust allowed us to get away with mutation here, say by going through node C somehow, we could call .clear() on that Vec, and that would make the &&Node double reference dangling! (Maybe the more realistic way to get into a situation like this would be to *iterate* over the Vec and then somehow try to clear it in the middle of your loop.)

  • @jaredbutcher3791
    @jaredbutcher3791 ปีที่แล้ว +2

    If I had seen this video existed a month ago, it would have saved me from spending a whole day banning my head into a wall.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +2

      thanks, I'm glad you found it valuable. it's the approach that I also would have preferred when first learning this topic.

  • @yoshiyahoo1552
    @yoshiyahoo1552 ปีที่แล้ว +1

    That is the first time I’ve seen just a scope be useful. No if statement no loop, just a scope.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      yeah they are good for ensuring deallocation once you no longer need something

  • @petermichaelgreen
    @petermichaelgreen 8 หลายเดือนก่อน

    You reffer to Cell, Refcell, Mutex and RwLock as smart pointers, but they are not pointers. The value stored is stored as part of the Cell/Refcell/Mutex/Rwlock not in a seperate location on the heap.
    Also while you can't use get on a cell containing a non-copy type, if your type implements Default (as for example String does) you can use take. So you can write code like.
    let tmp = cell.take();
    // do something with tmp.
    cell.put(tmp);

  • @zyxyuv1650
    @zyxyuv1650 ปีที่แล้ว +7

    Using the ' character for lifetime annotations is horrid and always unsettling to look at and parse with my eyes, and annoying to implement for editors/web views with lightweight syntax highlighting. Even writing it here in a post I'm worried about clarity and if it's hard to read. Rust should have used another keyword or @ or something, why is that operator so off-limits... It's not just an aesthetic problem, using ' actually causes language problems. For example it has ambiguity with trying to use const generic parameters of type char like if you wanted to use a type Foo without some special-case scenario. Didn't Rust learn from C++ about doing crazy stuff with parsing special corner case syntaxes? It's bad like the problems C++ inherited.

  • @pierreabbat6157
    @pierreabbat6157 ปีที่แล้ว +2

    I've written a C++ program that manipulates a TIN (a plane graph in which every region is a triangle) using three classes in a tangled hierarchy, at least two levels of locking, and readers-writer locks, to refine the TIN until it fits the point cloud. It took me about a year to get the multithreading working right. Every new triangle has to be created locked, and there's just one lock that controls adding new triangles, which will be a bottleneck when I run it on a 144-thread machine. (I have an idea of how to fix that.) How could this be done in Rust?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      It's a bit hard for me to answer without a better understanding of the low level details of your project, so let me flip it back to you - what aspects of Rust do you think would make implementing such a thing challenging?

  • @brielov
    @brielov ปีที่แล้ว

    What is that status line?

  • @AK-vx4dy
    @AK-vx4dy ปีที่แล้ว

    I have maybe stupid question... Why not use Cell, RefCell in adjacent vector and leave values in "natural state" ?

  • @porky1118
    @porky1118 ปีที่แล้ว +2

    When I started programming in Rust, I had to use interior mutability in some places, but after a while I just do things differently so I don't need this anymore.

    • @carlosmspk
      @carlosmspk ปีที่แล้ว +1

      How do you get around it?

    • @porky1118
      @porky1118 ปีที่แล้ว

      @@carlosmspk I don't really remember why I needed it to begin with. I just don't get into situations where I would need interior mutability anymore after I learnt how to use Rust properly.
      For graph like structures I just store indices of arrays or maps.
      Often it also helps to split a struct into multiple smaller structs, and pass them around.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      do you think there is a way around it in the scenario described in the video?

    • @porky1118
      @porky1118 ปีที่แล้ว

      @@codetothemoon This scenario is about graphs, and "For graph like structures I just store indices of arrays or maps."

  • @swapode
    @swapode ปีที่แล้ว +5

    I think it's worth pointing out that interior mutability should be seen as kind of a last resort. I say kind of because obviously there are plenty of situations where it's the right choice - but frequently it's used as a crutch to use Rust just like you would a garbage collected language, when just a slight change in how we think about memory or control flow would lead to better results. That's probably the hardest part about really learning Rust, but the cool thing is that once you get the hang of it, it's easily applied to other languages as well and tends to lead to better project structure.

  • @mrmimeisfunny
    @mrmimeisfunny ปีที่แล้ว +1

    0:39 IDK, that sounds like something you can reduce to the halting problem. Like imagine you had a program that segfaults if it discovers itself is memory safe and does nothing unsafe otherwise. That would be a contradiction.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      yes, I believe checking a program (that uses manual memory management) for memory safety is roughly equivalent to the halting problem.

  • @driden1987
    @driden1987 ปีที่แล้ว +1

    Will you be doing a Doom Emacs video ?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      Would you find that valuable? If so, what editors have you tried and which is your go-to at the moment? Trying to get a sense of what folks are interested in and where they are coming from.

    • @driden1987
      @driden1987 ปีที่แล้ว

      @@codetothemoon I've just kind of given up on emacs and went back to nvim, but it seems like a couple of people asked about the editor in the comments already and I always find those vids interesting

  • @almuaz
    @almuaz 4 หลายเดือนก่อน

    in 4:51, why didn't we try `&mut Node`?

  • @rockyessel
    @rockyessel ปีที่แล้ว +1

    Please can you make one big huge tutorial on with projects

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      I'm not sure what you mean - what sort of projects?

    • @rockyessel
      @rockyessel ปีที่แล้ว

      @@codetothemoon There aren't a lot of resources for Rust, and you're one of the channels I love so much and am grateful to.
      project: Any rust project that connects to data and connects to any frontend frameworks.

  • @sutsuj6437
    @sutsuj6437 ปีที่แล้ว +3

    One thing is that in rust you should first try to change your API, so that you don't need interior mutability, if that doesn't work only then should you consider using it.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      agree 💯!

    • @meowsqueak
      @meowsqueak 10 หลายเดือนก่อน +1

      @sutsuj6437 Can you give an example of what this would look like in this case?

  • @pudicio4895
    @pudicio4895 ปีที่แล้ว +2

    I can understand why people love this language but if I don't need the performance I prefer living with a GC. The hoops this throws are just crazy just to implement a simple graph structure..

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +2

      totally understand the sentiment that "its not worth it" in many cases. I think there will always be a place for GC 😎

  • @Lars-ce4rd
    @Lars-ce4rd หลายเดือนก่อน

    I was really expecting the comment section to be 95% rust nerds just saying "I already knew that"

  • @AndreFera43
    @AndreFera43 ปีที่แล้ว +1

    Is there a reason to use mutex instead of rwlock?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      see stackoverflow.com/questions/50704279/when-or-why-should-i-use-a-mutex-over-an-rwlock
      also in the scenario described by the video I think mutex is the better option because there isn't a need for a read lock at all

  • @johnyepthomi892
    @johnyepthomi892 ปีที่แล้ว +1

    Which keys are you using. Browns?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      Gateron Red Pros in a Corne! They feel so nice...

    • @johnyepthomi892
      @johnyepthomi892 ปีที่แล้ว

      @@codetothemoon Gateron is great! Keep using it. Very satisfying.

  • @adibhanna
    @adibhanna ปีที่แล้ว +1

    What editor are you using?

    • @SaHaRaSquad
      @SaHaRaSquad ปีที่แล้ว +1

      Doom Emacs, you can see it in the title bar at the top of the window.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      yep DOOM emacs! been using it for a few months now and I don't see myself switching to something else anytime soon.

    • @adibhanna
      @adibhanna ปีที่แล้ว +1

      @@codetothemoon I never used Emacs! how does it compare to neovim?

    • @SaHaRaSquad
      @SaHaRaSquad ปีที่แล้ว +1

      @@adibhanna Emacs has very different controls (by default), is less focused on pure text editing and comes with basically every feature imaginable, even if it doesn't make any sense.
      Doom Emacs is a popular alternative configuration.
      I personally hate Emacs' approach to many things but it's still one of the best editors out there.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      @@adibhanna IMO you can't go wrong with either - both are fantastic. The actual coding experience pretty much identical in both (albeit key bindings may be different), most of the differences exist outside of that. Emacs is famous for something called org mode, which is sort of like markdown but much more powerful. For example, you can include code blocks of any language in your org documents, and you can run them inside the doc similar to how you would in something like a Jupyter notebook. Much of what you can do in emacs can probably be replicated in nvim plugins, but it seems like the one thing emacs will always have over *vim is that it can be run as a terminal OR GUI application - when run as the latter, you get capabilities like having multiple fonts at the same time. Something that can really make things more aesthetically pleasing and that I don't believe is possible in a pure terminal application.

  • @oglothenerd
    @oglothenerd 7 หลายเดือนก่อน +2

    What makes you want to use MacOS instead of something like Linux?

    • @codetothemoon
      @codetothemoon  7 หลายเดือนก่อน +1

      I don't have an ultra strong preference for macOS over Linux for development - just don't make me use Windows 😎 right now the biggest thing keeping me on macOS is Apple's Messages app for texting from my computer. Honestly if that wasn't a factor I'd probably be using Linux

    • @oglothenerd
      @oglothenerd 7 หลายเดือนก่อน +1

      @@codetothemoon I am a FOSS activist, but I have to respect that. Well, at least we both can agree that Windows is a terrible dev environment!

  • @remcogreve7982
    @remcogreve7982 ปีที่แล้ว +1

    At the time this videos made or because of Allan Turing?

  • @havocthehobbit
    @havocthehobbit 4 หลายเดือนก่อน +1

    This sort of thing makes me want to go back to cpp but there are too many other advantages to using rust.

    • @codetothemoon
      @codetothemoon  4 หลายเดือนก่อน

      yeah there are some hoops to jump through when you can't live by the rules of the borrow checker...

  • @gabrielnuetzi
    @gabrielnuetzi ปีที่แล้ว +2

    I am just feeling wrong passing a non-mutable node but in the function change its members... Is that legit?? It seems like a codesmell

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      I can definitely relate to this! It feels so wrong! But unfortunately that appears to be the reality of compile time memory safety checks - there are some types of programs that, despite being memory safe, need to go around those compile time safety checks 🙁

    • @gabrielnuetzi
      @gabrielnuetzi ปีที่แล้ว

      @@codetothemoon Hm... I would rather try to pass `add_one` a `&mut Node` and still use a `RefCell` for single threading or `Arc` for threaded stuff... (?) Or rather not build the data structure of the graph like that, but instead with indexes and a global common list/hash-map... There is always a way I think one just needs to make the program work differently. A data structure linked by refs (pointers) is easy but anyway gets you in trouble also in C++ where you need to make sure these pointers point always to valid memory and do not get dangling because of reallocation of some underneath data structure which holds the nodes...

  • @sirnawaz
    @sirnawaz ปีที่แล้ว +1

    At around 5:00, why did you take the parameter as `node: &Node` if you want to mutate its value ? It's an immutable reference which will not allow you in general, irrespective of tree structure or the thing (Cell) you want to explain. You should have taken `node: &mut Node` and try mutating it.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      The premise of the video is what to do in situations where you'd like to take a mutable reference (or ownership), but you can't because there already exist multiple borrows of that piece of data. That's where interior mutability comes in, which is basically foregoing compile time borrow checking such that you're able to mutate things that have been borrowed "immutably".

    • @sirnawaz
      @sirnawaz ปีที่แล้ว

      ​@@codetothemoon Yes. I understood that. Thanks for saying that again. It's a great video.
      However, the point I was making is.. you had an opportunity to make a "full circle" argument. That is, when we beginners see a function that takes `node: &Node` as parameter, it seems immediately obvious to us that `node` cannot be modified .. and that is true, irrespective of the shape of the data-structure (that is actually wrong, as we see it later in this video itself, but that is what the beginners initially think). So logically, in order to mutate node, we have to change the parameter type to `node: &mut Node`, then we take 5 seconds and make the full circle argument that: while `&mut` does allow the function to mutate the node, we now cannot make two different nodes `b` and `c` refer to the same node `a`, as that has to be `&mut` type as well, which Rust doesn't allow. Hence, the need of `Cell` is clearly understood. We beginners tend to forget little concepts while we build our knowledge base in our mind, so such a "full circle" argument helps a lot.

  • @user-qq4wu8sc2k
    @user-qq4wu8sc2k ปีที่แล้ว +3

    TBH RefCell is a ductape of the Rust. Construction with whole purpose to turn of main feature of rust and which will crash your application even if there is no real reason for that. One of the worst parts of the Rust. The two another quite equaly bad parts is a macros and weird borrow checker rule which require mutable reference to actually go out of scope instead of track the last use in that scope.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      yeah i agree it is kind of like turning off the main feature of Rust, which is always preferable to avoid. It comes back to the intractable problem of accepting all memory safe programs while rejecting all unsafe programs. This intractability leads to these sorts of things being necessary. Also If you still want the safety, you can avoid the potential panics by using 'try_borrow' instead

    • @32zim32
      @32zim32 7 หลายเดือนก่อน

      You will panic in the end because what should add_urgent() function do of it can't get Mut borrow for some reason..

  • @Tomyk9991
    @Tomyk9991 ปีที่แล้ว +1

    When i am at this point, i know its not the right thing to do, especially in Rust, but i just use *const T or *mut T and live with the fact, that i am in an unsafe world at this context. Using the functions from outside are still safe to use, when coded propertly

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +2

      yeah I'd probably avoid this if possible, seems like it'd be foregoing some of the benefits Rust provides over C/Cpp

  • @recarsion
    @recarsion ปีที่แล้ว +3

    I'm wondering though, isn't a heavy usage of these kind of a red flag? Feels like fighting the borrow checker

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +2

      I think you'd definitely want to avoid using interior mutability when it isn't strictly necessary, and it does feel a bit like fighting the borrow checker. That said, the benefits of the borrow checker are huge and the cases where you need to work around it are likely to be few and far between.

    • @recarsion
      @recarsion ปีที่แล้ว

      @@codetothemoon Cool, thanks for the reply!

  • @dulanjala
    @dulanjala ปีที่แล้ว

    but they are slower than if there's no unsafe code at all... there's performance hit even for the simplest cases just because we can't express things clear enough... or I'm wrong..

  • @drvanon
    @drvanon ปีที่แล้ว +1

    One of your assumptions for the use of borrow_mut is incorrect: you assume that there would never be two borrow muts in your add one function, but the cycle case would create a borrow_mut for each loop of the cycle.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      Good point - I should have mentioned this much earlier in the video, but at 12:07 I explain that this program doesn't handle cycles. As you probably know we'd have to somehow keep track of the nodes we've already visited to avoid infinite loops (or panics, as would happen in case you reference)

  • @Dygear
    @Dygear ปีที่แล้ว +3

    How my rocks, would a RwLock lock, if a RwLock could lock rocs.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      Hah! this would have been a fantastic line to open the video with....

  • @Turalcar
    @Turalcar ปีที่แล้ว +2

    12:38 Arc could be avoided with thread::scope

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      I wasn't aware of thread::scope, thanks for pointing this out!

  • @Turalcar
    @Turalcar ปีที่แล้ว +1

    12:07 I wouldn't call it "doesn't handle". Graphs with cycles will be rejected at compile time.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +1

      How would it be able to detect a cycle at compile time? What would the error be? And how would we be able to get around that (since cycles are required for some applications) ?

    • @Turalcar
      @Turalcar ปีที่แล้ว

      @@codetothemoon Depends how you try to write it. The fact that graph edges are references to already constructed vertices requires that all edges go "upwards" (in source code). This guarantees there are no loops.

    • @Turalcar
      @Turalcar ปีที่แล้ว

      Well, I guess you could make a node mutable and add edges after construction. But we can do that only if it has no incoming edges (since those are immutable borrows).

    • @Turalcar
      @Turalcar ปีที่แล้ว

      @@codetothemoon Go around loops: like you did with Arcs. Or you could use an arena: keep all nodes in a single slice and refer to other nodes by their index instead of an actual reference

  • @stolkovandrew
    @stolkovandrew ปีที่แล้ว +7

    Enooms

  • @thomasandolf7365
    @thomasandolf7365 ปีที่แล้ว

    i have watcched so many videos about RefCell and Rc and what all tutorials fail on is that no one shows a real world problem applying Rc or RefCell. Every one builds these simple basic graphs that is not applicable on a real life problem. My suggestion to you is that in your tutorial you set out to solve a specific problem instead, that can only be solved by using interior mutability, instead of building this fictional simple graph. Just some feedback.

  • @Turalcar
    @Turalcar ปีที่แล้ว +2

    0:40 Static analysis that accepts all memory-safe programs and rejects all non-memory-safe programs is impossible as a consequence of the halting theorem, duh.

  • @AlexAmellal
    @AlexAmellal 5 หลายเดือนก่อน

    Why fight the borrow checker instead of learning how to adopt rust's intended paradigm?
    Specific program instances that are memory safe are not necessarily memory safe in general. These exceptions are among the situations that rust avoids by design.
    The little "hacks" or circumstantially memory safe bits of code that appear early in the development cycle are the seeds of infinite hell down the road when system complexity increases.
    What could have been "clearly memory safe" code snippets at an earlier stage can grow into messy reference violations down the road -- *exactly* the kinds of headaches from C/C++ development that played part in motivating rust's new paradigm.
    So I ask: if the developer is going to outsmart the borrow checker whenever it's inconvenient, why not just code in C++?

  • @shinyjonny1658
    @shinyjonny1658 ปีที่แล้ว +2

    One of the greatest benefits of Rust is that it makes you uncomfortable using worse patterns.
    Sure, you can implement it as a traditional graph, but you could also implement it as an entity component system with a vector of nodes and a vector of relationships between them.
    That makes it:
    1. Memory safe
    2. Cache-friendly
    3. Without the overhead of reference counting
    I'm not saying people should not use RefCell, but people should ask themselves: Do I need it? Or do I want it because that is how it's done in C++/java/...? And is there a better pattern?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      How would you implement an O(n) graph traversal when relationships between nodes are stored in a vector? I also don't see how this would negate the need for interior mutability, since each node would potentially have multiple shared references to it in said vector

    • @shinyjonny1658
      @shinyjonny1658 ปีที่แล้ว

      @@codetothemoon the relationship vector would contain indexes of the children, not references. You just need to know the index of the node. Using that index in the node vector gives you the node data, and using it in the relationship vector gives you data containing the indexes of children. This gives you O(n) traversal, i believe.

  • @theLowestPointInMyLife
    @theLowestPointInMyLife ปีที่แล้ว +3

    So what's the benefit of adding all this complexity?

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว +2

      which complexity are you referring to specifically? In the video I was hoping to show how interior mutability is simple :) I think the borrow checker definitely introduces some complexity, but complexity that is well worth the memory safety it yields in return!

    • @theLowestPointInMyLife
      @theLowestPointInMyLife ปีที่แล้ว

      @@codetothemoon I've never had an issue with memory safety, its not rocket science to keep track of allocations, especially with smart pointers. This just looks like an unnecessarily complex way of doing something really simple like accessing a vector in a struct.

    • @TON-vz3pe
      @TON-vz3pe ปีที่แล้ว

      @@theLowestPointInMyLife If you learn to understand complex then you would easily do it the next time without falling into traps. I think to the Author this is not complex because he is experienced in Rust. Don't you want to become like him?

    • @theLowestPointInMyLife
      @theLowestPointInMyLife ปีที่แล้ว

      @@TON-vz3pe not particularly, Im very happy with C++, use rust very minimally in the rare case it has a better library than is available in c++

    • @xGOKOPx
      @xGOKOPx ปีที่แล้ว +1

      @@theLowestPointInMyLife "I've never had an issue with memory safety" - good for you. Unfortunately, most programmer aren't as brilliant as you are. Microsoft said that 70% of their security bugs are memory safety issues

  • @plutonium_guy
    @plutonium_guy 8 หลายเดือนก่อน

    at 4:28 , i be like, bor just add clone and copy and finish the code itself

  • @lionbryce10101
    @lionbryce10101 ปีที่แล้ว +3

    That snippet at 0:26 is why I haven't learned C++ or Rust
    Syntax is getting out of hand

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      I can definitely empathize with this - it does feel a bit more verbose than it needs to be. I'm hopefully that at some point explicit lifetimes won't be necessary for this scenario

  • @9SMTM6
    @9SMTM6 ปีที่แล้ว

    Depending on who you see as your target audience, showing some use cases for std::mem::{take,swap} on &mut and how they combine with zero-allocation default values for eg. Vec could also be helpful.
    Otherwise someone coming from C/C++ doing some high performance work might wonder how to do that and instead use something like Option, which leads to a brittle application or at least one that has to somehow cover a lot of failure cases that are not actually possible.

  • @user-hj8rn5wp8z
    @user-hj8rn5wp8z 4 หลายเดือนก่อน

    why you did not create "universal" constructor, that will accept string and to typisation underhood?

  • @dinhero21
    @dinhero21 3 หลายเดือนก่อน +1

    I belive it is impossible to have a program that can 100% of the time guarantee that a program is memory safe or not because of the halting problem.
    Say you have a function S that takes a program as input and returns true if its memory safe and false if its not
    Then a function L that is leaks memory and is unsafe, so any other function that calls L will also leak and be unsafe.
    Now, construct a function C that takes some source code as input, passes that source code into S, then if S returns true then it simply ends, if S returns false then it calls L and ends.
    Now, pass C's source code into C:
    1. C is called with C as input
    2. S is called with C as input
    3A. If S returns true (C is safe)
    4A. C calls L
    5A. L leaks memory
    6A. L is unsafe
    7A. C is unsafe -- Contradiction! By definition, S NEVER fails and here it predicted that C is safe
    3B. If S returns false (C is unsafe)
    4B. C ends
    6B. C is safe -- Contradiction! By definition, S NEVER fails and here it predicted that C is unsafe
    S can only return true and false but both of those values are wrong meaning that it is impossible to have a function that correctly predicts if a given source code is safe or not in all cases.

  • @10x-developer
    @10x-developer ปีที่แล้ว

    Nice and crispy video just too fast for me

  • @chriswhealy4170
    @chriswhealy4170 3 หลายเดือนก่อน +1

    Great explanation, but as a teacher myself, I would caution that if you really want your listeners to absorb what you're communicating, then you must significantly slow down your rate of speech. There are at least two reasons for this:
    1) The comprehension of new concepts takes time. Therefore, although you're delivering great content, in order for your lesson to be really effective, that content cannot be delivered at conversation speed (or here, almost machine gun speed). You must consciously slow down your rate of delivery in order to give your listeners the time to absorb and comprehend these new facts and concepts
    2) If a native English speaker finds it hard to keep up, how much more challenging will it be for someone whose first language is not English? Always keep of the non-native English in mind
    Great video otherwise!

    • @codetothemoon
      @codetothemoon  3 หลายเดือนก่อน

      thanks for the feedback, it is super helpful! i do indeed struggle with pacing, and the common feedback in this era was that things were too fast. I've corrected a bit but I could probably still do better!

    • @chriswhealy4170
      @chriswhealy4170 3 หลายเดือนก่อน

      You're welcome.
      What helped me the most was teaching non-native English speakers. These people are perfectly intelligent, but in relation to the subject matter I was talking about, they were simply uninformed. Therefore, in order to reduce the effect of the language barrier, I had to deliberately slow my speech down and rephrase what I wanted to say in the simplest possible terms without the use of slang or idiom.
      This not only helped the students comprehend the lesson, but also helped me distill my knowledge down to the core concepts.
      It really is a win-win situation for everyone!
      🙂

  • @parlor3115
    @parlor3115 ปีที่แล้ว +1

    Yep, probably not going to become a Rust dev

  • @vsuryabhargava
    @vsuryabhargava ปีที่แล้ว +1

    I'm learning rust at the moment and I stumbled on this video th-cam.com/video/N-E-qtQhsHw/w-d-xo.html where at 21min into the video Jonathan says that it's possible to encode the business logic of an application onto the type system of rust. I've been trying to find examples of that cause that seemed pretty cool. Can you make a video or point out some resource which explains how we can do that?
    I've found th-cam.com/video/pwmIQzLuYl0/w-d-xo.html which I found is pretty interesting but I'm not sure if this is what Jonathan was talking about in the video.

    • @vsuryabhargava
      @vsuryabhargava ปีที่แล้ว +1

      Sorry forgot to mention, your videos are awesome and I really like how to the point your videos are.

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      I don't have my head completely wrapped around the concept yet but I think he might be referring to a Turing complete type system. Stack overflow thread here: stackoverflow.com/questions/34002061/what-is-the-reason-for-a-turing-complete-type-system

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      thank you!

  • @DummyFace123
    @DummyFace123 ปีที่แล้ว +1

    Good for me, but not for thee 😏

  • @alterX2ego
    @alterX2ego ปีที่แล้ว +1

    holly f this is complicated !!! :(

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      darn, this is the reputation interior mutability has and i was hoping to change it with this video lol

  • @olsuhvlad
    @olsuhvlad ปีที่แล้ว +1

    29 The next day John seeth Jesus coming unto him, and saith, Behold the Lamb of God, which taketh away the sin of the world.
    30 This is he of whom I said, After me cometh a man which is preferred before me: for he was before me.
    31 And I knew him not: but that he should be made manifest to Israel, therefore am I come baptizing with water.
    32 And John bare record, saying, I saw the Spirit descending from heaven like a dove, and it abode upon him.
    33 And I knew him not: but he that sent me to baptize with water, the same said unto me, Upon whom thou shalt see the Spirit descending, and remaining on him, the same is he which baptizeth with the Holy Ghost.
    34 And I saw, and bare record that this is the Son of God.
    35 Again the next day after John stood, and two of his disciples;
    36 And looking upon Jesus as he walked, he saith, Behold the Lamb of God!
    37 And the two disciples heard him speak, and they followed Jesus.
    (Jn.1:29-37)

    • @codetothemoon
      @codetothemoon  ปีที่แล้ว

      The disciples can be nodes B and C and Jesus node A as they are both following him!

    • @olsuhvlad
      @olsuhvlad ปีที่แล้ว

      @@codetothemoon You can be a disciple of Jesus, for example node D. :)
      20 Neither pray I for these alone, but for them also which shall believe on me through their word;
      21 That they all may be one; as thou, Father, art in me, and I in thee, that they also may be one in us: that the world may believe that thou hast sent me.
      22 And the glory which thou gavest me I have given them; that they may be one, even as we are one:
      23 I in them, and thou in me, that they may be made perfect in one; and that the world may know that thou hast sent me, and hast loved them, as thou hast loved me.
      24 Father, I will that they also, whom thou hast given me, be with me where I am; that they may behold my glory, which thou hast given me: for thou lovedst me before the foundation of the world.
      (Jn.17:20-24)
      24 Verily, verily, I say unto you, He that heareth my word, and believeth on him that sent me, hath everlasting life, and shall not come into condemnation; but is passed from death unto life.
      25 Verily, verily, I say unto you, The hour is coming, and now is, when the dead shall hear the voice of the Son of God: and they that hear shall live.
      (Jn.5:24,25)