Rust Powered Polymorphism ⚡️ With Traits

แชร์
ฝัง
  • เผยแพร่เมื่อ 12 ม.ค. 2023
  • A quick overview of object oriented programming and polymorphism in Rust.
    ---
    Stuff I use to make these videos - I absolutely love all of these products. Using these links is an easy way to support the channel, thank you so much if you do so!!!
    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
  • วิทยาศาสตร์และเทคโนโลยี

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

  • @mk72v2oq
    @mk72v2oq ปีที่แล้ว +308

    Worth mentioning that "prefer composition over inheritance" principle is general for any language. Rust just takes it as the standard and makes inheritance obsolete.

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

      very true, good point! ditching inheritance makes code infinitely more readable imo...

    • @phenanrithe
      @phenanrithe ปีที่แล้ว +32

      That's a common misunderstanding of OO techniques. Composition and inheritances are two different patterns for two different needs (search for "has-a" and "is-a"), one doesn't simply replace the latter with the former. Rust just lacks inheritance at the moment, which leads to a class of issues for specific problems to solve, unfortunately. It's possible to work around but it requires to duplicate the code, which makes it hard to maintain. Or by using macros, which makes reading the code much more difficult.

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

      Yes. Mostly. For game engine frameworks for instance you will need to store all data in one place like a vec for centralized storage so that you can do multi threading. That requires down casting which again requires up casting to Any first when you need access to data. For now up casting is an unstable feature. But it seems to work so far. The problem is that if you did cast to Any via your own functions inside a custom trait that is not Any. That you have to do that for any game node all over again because you can not make a default trait because of life time issues and seized issues. Horrible pain in the neck. But up casting is being stabilized so it is coming to stable Rust in the future.

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

      @@phenanrithe Can you give examples? It would help

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

      Is Rust even an object-oriented language?

  • @Julian-vi4vl
    @Julian-vi4vl ปีที่แล้ว +45

    One place where you really cannot escape the dynamic dispatch is when you have mixed types like a vector that can contain both SUV and Sudan

  • @Possseidon
    @Possseidon ปีที่แล้ว +289

    This would've probably went over the scope of what you were trying to show but for those interested:
    If you want anything that implements both `LandCapable` and `WaterCapable` to automatically implement `Amphibious` as well, you can do so:
    impl Amphibious for T {}
    Which can be read as "implement `Amphibious` for any type T that implements `LandCapable` and `WaterCapable`".
    There is also alias traits in unstable, that basically do more or less the same thing but with less boilerplate:
    trait Amphibious = LandCapable + WaterCapable;

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

      Great point, I probably should have covered this as well - it would make things much more concise if you have lots of amphibious vehicles

    • @Singhrager
      @Singhrager ปีที่แล้ว +12

      @@mathijsfrank9268 I think you may be reading it the wrong way around. The example does not mean that being Amphibious implies being LandCapable. It means that, if you are LandCapable (regardless of whether you customize drive) and you are WaterCapable, that implies that you are Amphibious. So you still only have one implementation of drive, i.e. the one you go with when you implement LandCapable.

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

      oh man, every day, after 5 years, I still learn something new about Rust.

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

      gone*

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

      You can also make T ?Size so it works on trait objects too.
      impl C for T {}

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

    Worth mentioning that `impl Trait` is just syntax sugar for `fn road_trip(vehicle: &T) {}`

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

    Your clear and concise way of explaining things really helps me to learn more about Rust. Looking forward to the next episode...Thank you!

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

      WOW thank you so much Mark!! I really appreciate your support and your kind words. Thanks again for watching!

  • @BulbaWarrior
    @BulbaWarrior ปีที่แล้ว +24

    I think it's important to note a naming convention for traits used in rust: if your trait implements one function it should be named the same way as the function. So in this example idiomatic names for LandCapable and WaterCapable would be "Drive" and "Float". It is nice to know the convention as many of the standard traits are named this way (for example From and IntoIterator)

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

      Pretty sure the implications is that being "LandCapable" will do much more than just provide a single drive method.
      And on a small tangent. If your trait IS just what function. What's really the benefit os using a trait over just writing a generic drive function that you call as: drive(suv)?
      (Genuine question. Since I would be surprised if rust made some nice optimization in one case vs the other)

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

      @@sebastiangudino9377 I think you are mixing things together. LandCapable is not a type, its a trait, so you can't pass it as a generic parameter. The correct call would be drive::(suv), but then think about what drive does: it has to work for all types that implement LandCapable, which means that you can only use functions from the LandCapable trait. But we have just decided to move the only function out of LandCapable, so drive can't really do anything meaningful now.
      Now let's look at why having a single function in a trait is a good thing. Suppose LandCapable has another method, I will call it fuel(). Now look at road_trip(): it only cares that its argument implements drive() and does not really care about fuel, so fuel() is redundant here, now imagine we have a bike that can't really be fueled. A better more flexible approach would be to have two traits: Drive and Fuel. Then functions that care only about drive will use just the first trait and some other functions will require both traits to be implemented - your code is more flexible!
      TLDR: think of traits not as objects but properties of objects, which work better when they are granular. Hopefully I made my point clear

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

      @@BulbaWarrior Ups yeah, i mixed the Syntax up quite a lot. But you thankfully understood what I meant! And yeah, I guess you are right. Rust is deeply related to composition. Weird at first. But seems like a really nice abstraction as things scale up

  • @cd-bitcrshr
    @cd-bitcrshr ปีที่แล้ว +8

    Was stuck wondering how to do something in a Rust project, and you just went ahead and put the solution on a platter for me. Excellent video, as always.

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

    Whoa!! the way you explained the zero cost abstraction is mind blowing!!

  • @marcusrehn6915
    @marcusrehn6915 ปีที่แล้ว +12

    This feels like a far superior way to do OOP than what I am used to see in other languages.

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

      I like it as well!

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

      What advantage do you mean?

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

      It might be safer but it is not superior compared to traditional OOP languages because you need to write much more code

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

      @@Tienisto Compared to Java or C++?

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

    Amazing video. You break down these rust concepts better than anyone else! Much appreciated as a TS/JS dev!

  • @sergiuoanes4635
    @sergiuoanes4635 ปีที่แล้ว +35

    Absolutely love your videos. Simple examples straight to the point. Keep them coming! thanks

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

      wow thank you so much for your support and kind words! more to come!

  • @Kodlak15
    @Kodlak15 ปีที่แล้ว +21

    This aspect of Rust has been really hard for me to wrap my head around. Perhaps even more so than ownership/borrowing/lifetimes. Thanks as always for the great content. This was helpful 😁

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

      Nice, really happy it helped!

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

      I think it's because most people didn't learn these concepts of composition as beginners to programming. We instead swallowed OOP principles like that of Java. But things are changing and Rust is designed to be powerful, not simple and easy-to-learn.

  • @aditeya1024
    @aditeya1024 ปีที่แล้ว +16

    I was writing a ray tracer in rust and this video was super helpful in explaining a trait!

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

      nice, really happy that it helped! and props to you for tackling a ray tracer, that's quite an undertaking!

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

      i hope you'll succeed and i'll be really happy if you'll let us know!!! all the besttt

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

      What do you use to draw a single pixel on screen ? Was interested to learn rust doing a raytracer, even a basic one who does not use the gpu at first

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

      @@gaxkiller i use the ppm format, which just writes the rgb values of each pixel. Though I think you can use the image crate to convert to jpg/png

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

      @@aditeya1024 Thx ! Ok so you write in a file, not on screen, perfectly fine but you cannot do "interactions" (move the camera, etc)

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

    Very nice video, I love your Rust content, keep going!

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

    Oh man, I'm so glad that I subscribed to this channel. I think your explanation is obvious. Thank you and keep up the good work.

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

      thanks so much for the kind words!

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

    I like your video style, its getting better with each one
    +1

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

    This video helped me understand the difference between the dyn and impl syntax. Thank you!

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

      nice, really happy you got something out of it!

  • @kippie80
    @kippie80 ปีที่แล้ว +12

    Didn't realize &impl and &dyn were so interchangeable, thanks!

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

      nice, glad you found it valuable!

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

      They are not really interchangeable. Using "impl" is just syntactic sugar for a generic function, so as explained in the video the compiler will instantiate this function for each type that is used. This also means you cannot use it for example with a collection holding different types with the trait - for that you must use "dyn" and its virtual table (and that collection will also need to use fat pointers).

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

    Really appreciate these videos. Keep up the good work :)

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

      wow thank you so much for the support Jan!!! more to come!

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

    There are two very practical advantages of traits compared to inheritance base polymorphism: automatic implementation (if your type implements other specific traits), and automatic derivation. Because traits are seperate piece of code from your datatype it is ok to generate implementation for them automatically as this does not affect existing code base, compared to generating methods for interfaces.

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

    Tnx! This actually helped me understand the trait system in rust. I know 'traits' from PHP, but I never found a situation where it could be useful (its just horizontal inheritance basically). The way Rust uses traits makes much more sense to me.

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

      nice! really happy the video helped you understand Rust traits!

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

    Very focused and clear explanation 👍 The impl instead of dyn was something new to me

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

      Thank you, glad you found it valuable!

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

    Thanks for this! thought I knew the basics already. I didn't even know that &impl Trait existed, and I'm not even finished watching yet.

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

    amazing video. thank you so much!

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

      thanks, really happy you liked it!

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

    loved the video, keep making more

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

    excellently explained

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

      thank you, glad you liked it!

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

    thank you 👍⚡️

  • @2002budokan
    @2002budokan 6 หลายเดือนก่อน +2

    Excellent small examples.

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

    Hi there, i was wondering if you had a link to your dotfiles? Reason being, I love the way your emacs looks.

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

    Great video about rust traits, especially the super trait was very interesting.
    Of topic question: what editor do you use? I remember you used vscode, but now it seems you switched to (neo)vim? Btw it also seems you have a new keyboard - not so clicky and easier on the ears for the video 👍

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

      The editor is doom emacs.

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

      thanks, really glad you liked it! I'm currently using DOOM emacs which I'm really enjoying at the moment. And I am also trying a new keyboard called a Corne - it's pretty amazing and I can't see myself going back at this point

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

      @@codetothemoon do you have your doomemacs config shared somewhere? I tried to enable inlay hints but failed.

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

      @@codeshowbr actually i don't believe I did anything special other than uncommenting (rust +lsp) in init.el, and I *think* also uncommenting "lsp" in the "tools" section

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

    Great video, just wanted to let you know that for struct naming semantics when you have multiple capital letters next to each other you are actually only supposed to capitalize the first one, e.g. Suv not SUV, Html not HTML

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

    I love your videos, I like when you insert some images/videos to make it clear what you mean by landvehicle for instance. It is just a bit of alot of images switches in the video.

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

      thanks for the feedback, we are always trying to make things entertaining while not being too obnoxious, sometimes that's a fine line to traverse!

  • @jm-alan
    @jm-alan ปีที่แล้ว +6

    I've been working with Rust, learning on my own, for like a year now, and just today from this video learned that dyn is specifically referring to dynamic dispatch 😅
    Like, duh, that makes perfect sense, but I just kinda took it as "dynamic means runtime processed aka vtable lookup" without stopping to think

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

      nice, really glad you got something out of the video, despite likely already being familiar with many of the concepts!

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

    I've noticed you seem to be editor-hopping a lot :P first VSCode, then nvim, then helix, now doom emacs?? What are your thoughts on what you'll settle with or is this just for fun?

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

    Dynamic dispatch is also extremely good when combined with Reference-Counting f.e. "Rc"
    and combined with Any we can even do some limited downcasting
    "prefer composition over inherintance" sure... but ngl... sometimes if you dont just have shared functionallity... but also shared data... it becomes a mess of delegations... which imo is not ideal...

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

    One thing that is hard to do in Rust compared to other languages like C++ and C# is casting a trait to another trait. Like if you have a Box, you cannot check at runtime if the type stored in that variable also implements WaterCapable, whereas is C++ you can use dynamic_pointer_cast for that, and in C# you have the "is" and "as" keywords. I mention it because I've been rewriting code from those two languages to Rust, and I'm struggling to come up with the right patterns to replace these dynamic casts.

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

      you could add a try_as_x() method to the trait, that in the default implementation returns None, but you can override it so it convers the type.
      like
      struct Foo;
      trait X {
      fn try_as_y(&self)->Option {None}
      }
      trait Y {
      fn try_as_x(&self)->Option {None}
      }
      impl X for Foo{fn try_as_y(&self)->Option {Some(self)}}}
      impl Y for Foo{
      fn try_as_x(&self)->Option {Some(self)}}

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

      @@PeterAuto1 It's just kind of awkward that I have to list out all the traits I want to be able to cast into, and then remember to override the cast function for every type that implements the corresponding trait. I had found some crates that apparently generate this boilerplate code with macros, but they don't have that many downloads, so I figured maybe I just shouldn't be doing that in the first place. But thanks for the tip anyway.

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

      You could use trait downcast

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

      i know this is an old comment, but there is std::any::Any in the standard library for this exact thing

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

      @@homelikebrick42 Not quite. Any only allows casting to a concrete type. What I wanted was to cast a trait to another trait. For example, given a list of dyn Sensor, get all the items that implement the Thermometer trait, and then call a method from that trait. This is what is easy to do in C# and C++ but not in Rust. In Rust I have to add a method to Instrument with a default implementation (so that things that are not Thermometer don't have to implement it just to return an error), and then remember to override it where needed. It's kind of annoying. So now I'm trying to unlearn years of OOP so I can structure my code better to stop fighting against the language and avoid the problem altogether.

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

    Easy to read. May I ask a question: what's your workaround on Trait object with generic function parameter? Why this kind of Trait object is unsafe?

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

    cool quick tutorial, just found out about dyn and impl

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

      thanks glad you got something out of it!

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

    thank you

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

      wow thank you so much for your support!!!!

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

    Darn, I didn't even realize you could choose between dynamic dispatch and static dispatch so concisely. And I didn't know about supertraits.

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

    Would it be possible to implement amphibious directly without having to implement lang capable and water capable?

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

    I think I missed the twist :D was it the impl vs dyn? :)

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

    Tnanks, just awesome!!! VERY IMPORTANT QUESTIONS:
    1. What is the name of your VS Code theme?
    2. How did you make highlight the current line number?

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

      It's not VSCode, it's doom emacs. Not sure exactly what that is, but he said it in another comment.

  • @user-hn1cy5ee5l
    @user-hn1cy5ee5l 3 หลายเดือนก่อน

    This is common use case when you need to implement some behaviour which uses some data + also you want to have some structs sharing some field sets. Instead you invent a wheel in rust to achieve that, by implementing getters/setters to use them in default implementation

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

    I think you should have mentioned that `` is the normal syntax for a trait bound, and `impl MyTrait` is just a shorthand with the limitation that you can't reuse it in multiple places, e.g. as both argument and return type.

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

    What is the difference between static dispatch and generics with trait bounds? Im a beginner and have never even seen the use of 'impl' in a rust function signature.

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

    thx for your effort
    what keyboard and IDE do u use?

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

      thanks for watching! Keyboard is Corne v3 and IDE is DOOM Emacs

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

    very nice

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

    thank you, that was easy to understand.

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

      thanks, glad you liked the format!

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

    Can we use vars from base struct in derived one?

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

    👍Thanks!

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

    Building my first REST API using axum and sqlx, and I wanted to use `traits` in order to be able to swap out instances of certain aspects for their mock equivalents. Unfortunately, since so much of the code requires `async`, this proved to be impossible. I know in the nightly compiler there's _some_ support for async trait members, but I'm honestly more interested in getting myself to a place where I can optimize away most of the `async` to make things more testable.
    I started my career in C/C++, and then moved to Front End in the latter portion of my career, where I've become addicted to 80% Test Coverage minimums in the professional space, and 100% test coverage minimums in my personal projects. This has proved to be _quite_ the exercise moving back to strongly typed languages haha: Almost exclusively due to mocking.
    I'm a huge advocate of simple input-output and keeping most functions as simple as possible in order to make them easier to test. In the frontend space, it's super easy to swap out a struct with something that _looks_ the same, but functionally isn't. This has proven quite the task in Rust 😂

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

      I see more and more "Integration-style Tests" in Rust and C/C++ code bases than Unit Tests, which I feel adds complications which cloud the purpose of the function and the tests, making the code less stable overall.

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

      If you dive into rust for pratical uses you need to turn everything into async, so don't worry about that and do use async traits, also traits are really useful for mocking and testing and my company uses it all the time. But also makes so your struct has this contract (the trait) that tells you what it needs to implemento to be used for your porpose. This way you can always add new providers or mantain your code using this trait that tells you what your code needs to do. Here is one example:
      Imagine your service will hire a payments api service, and you build a Client for it that is able to call all the api's of the service. This endpoints are from your provider and there is no personal logic of yours. Now you need to not only call a endpoint, but multiple, or transform data before using it. This logic will go in your trait PaymentProvider or something like that. Another thing that can be useful for doing this is. Imagine that this Client struct is used by many services in your company. But your service only use a few of this endpoints. In your personal service trait you will only specify those endpoints that you need. My point is that this traits that are placed for mocking will be used for other reasons

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

      @@JosephDalrymple About this integration-style tests I can say that usualy mocking is always the way for calling other services or providers and only testing integration with your database is useful, which always is easy to replicate for testing and doesn't make it unstable

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

      ​@@leviwebercosta8154 Unfortunately, spinning up, populating, and spinning down a database tends to be heavy, and shouldn't be done as a regular test of your codes functionality. These tests are great because they're End-To-End, but Unit Tests should make up the bulk of tests for any given application.
      Unit Tests typically test a single function at a time. But this can be difficult when async traits are not yet fully supported in Rust. While there are workarounds in the meantime, the problem in and of itself is already quite a complex one to solve, given the need to calculate lifetimes beyond what is currently done for structs with standard methods. Because of this, its not a trivial task to pivot from concrete async structs to dynamic async traits, especially when the only gain comes in the testing world.
      Most of what I've done to alleviate that is to create #[cfg(test)] and #[cfg(not(test))] implementations of my structs, which is a major pain, but it gets around having to deal with the immense overhead of introducing modular functionality just for testing purposes, when there isn't much else to gain.
      A more attractive solution would be the ability to define a mod.mock.rs or something to define the mock implementation of a struct for testing purpose. It's just not worth the overhead to introduce additional heap allocations simply to make testing more intuitive. That has unnecessary real-world implications on your application's performance.

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

      @@JosephDalrymple I can only atest to how we do things at my job, whe usually use traits with async_trait library, and mock with mockall for unit testing. the services dont have any problem and no problems in performance.

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

    like your style.

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

    Looking all around for examples of a Vec or other collection contains a bunch of different subtraits, which in your case would be vehicles. Vec. Temporarily stuck on this.

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

      I know this is an old question but I had to do sth similar lately. I just created an enum which variants contain the things with different traits.
      Then you can have a vector of this enum and can match over the enum to get to the desired element (subtype).

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

    Had no idea super traits were a thing!

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

      nice, love it when folks who already know about the video topic are still able to get value!

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

      @@codetothemoon It's hard to find intermediate level content on Rust, so thank you for all the videos you make!
      I'm finding that going from being adequate at Rust to being good at it is a very long journey.

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

    It seems to me adding impl WaterCapable and impl LandCapable for Hovercraft is redundant since the Hovercraft is Amphibious which is defined already as both WaterCapable and LandCapable. Could you please explain why we still need to add those?

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

      The supertrait bound only means that any type which implements Ambhibious is required to also implement WaterCapable and LandCapable, it doesn't do the implementation for you (not least because the implementation usually has functions in it which you are supposed to write). If you wanted to get an automatic implementation, you would not have "trait Ambhibious: WaterCapable + LandCapable" but instead have "impl WaterCapable for T { ... }", and this implementation would be used even if you only have "impl Ambhibious for Foo". But beware, if you do this then you will not be allowed to also write "impl WaterCapable for Foo", as this would result in two implementations of WaterCapable for Foo and rust doesn't like that.

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

    I'm curious if the Rust community would be interested in the capability to Copy instead of using Fat Pointers. In other words, allow the compiler to be modified in such a way that the project you're building (maybe not the dependencies, since they weren't built with that option) to choose where the cost is incurred.
    Granted, that would essentially turn Traits into a type of Generics.

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

    What kind of dynamic dispatch does Rust have though? Single(as Java, C++,C#, etc) or Multiple (CLisp) ? I mean, say we now have super trait "Surface" and "Road" and "Ice" extends it. Then 'drive' would take "&dyn Surface" and, say, would print "Driving/Floating on {surface.name()}".

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

      Here is the test, if I got it right.
      Code:
      #![feature(trait_upcasting)]
      trait Surface {
      fn name(&self) -> &str {
      "unknown surface"
      }
      }
      trait Road: Surface {
      fn name(&self) -> &str {
      "road"
      }
      }
      trait Ice: Surface {
      fn name(&self) -> &str {
      "ice"
      }
      }
      struct Street {}
      impl Surface for Street {}
      impl Road for Street {}
      struct Glacier {}
      impl Surface for Glacier {}
      impl Ice for Glacier {}
      fn print(surface: &dyn Surface) {
      println!("Driving/Floating on {}.", surface.name());
      }
      fn main() {
      print(&Street {} as &dyn Road);
      print(&Glacier {} as &dyn Ice);
      }
      Output:
      Driving/Floating on unknown surface.
      Driving/Floating on unknown surface.

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

      Rust has single dispatch, an influence from C++. Bjarne has written at length about the difficulties of implementing multiple dispatch in a systems language.

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

    At 5:20 you said "Rust" which is lol because I'm here to learn about it 😀 Jokes aside good bite sized tuts, cheers

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

      Thanks, glad you found it valuable!

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

    What editor and theme is that? its fkin beautiful

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

      doom emacs, monokai-classic

  • @chris.davidoff
    @chris.davidoff ปีที่แล้ว +1

    I'm really curious what the performance difference of impl vs dyn really is.
    I suppose this would be a good mini-challenge/project for me to do :P

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

      yeah, it would be an interesting test - i'd be shocked if nobody has posted the results of such a test yet...

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

    Have anyone mentioned the most "Rusted" variant for the function? fn road_trip(vehicle: &T). This also allows us to make the function traverse_frozen_lake without making any "aggregation" traits (Amphibious). Just like that: fn road_trip(vehicle: &T)

  • @user-by2tg1xt7u
    @user-by2tg1xt7u 5 หลายเดือนก่อน

    Is there a problem putting a function inside an impl block without a "self" in order to associate it with that group, kind of like a class method would be? How would I otherwise implement something that is like a class method?

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

    Not sure what the curve ball was but I do think that it’s great that rust lets you generate templated versions of functions. But at the end of the day a VTable lookup isn’t the end of the world.

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

      The curve ball was that you can't just use a trait as a parameter type, you have to specify 'dyn' or 'impl'. In most languages that's a decision that you don't have to make.

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

      @@codetothemoonfair enough 👍

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

    I don’t think having to annotate parameters as being “dyn” is an example of a ZCA. This is just the compiler requiring you to… actually specify the parameter type. A trait is not a type, it’s just a constraint. Types describe the structure of some set of data of memory. Traits are just descriptions of the operations you can perform on some unknown set of data.
    The data being passed as the argument is completely different for dyn and non-dyn parameters. The former is a fat pointer to a vtable and to an object. The latter is the full set of data (or a pointer to it if we’re using references).
    Hence these are different types. “dyn” is a type qualifier just like “mut” is and the compiler is not being overly picky by requiring you to use it.

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

    Something which is weird is that the compiler gives ‘dyn’ as solution instead of the faster ‘impl’. That’s most likely because generics is harder to use for devs? Or what is the reason?

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

      I was wondering about this as well, I'm actually not sure!

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

      @@codetothemoon impressive answer from chatgpt 😜:
      “The Rust compiler does not necessarily prefer dyn over impl in function signatures. The use of dyn and impl has different implications and may result in better or worse outcomes depending on the situation.
      In general, impl is suitable for specifying the exact implementation details of a type, while dyn is suitable for specifying a trait object that exhibits a certain behavior but whose exact implementation is not important.
      In function signatures, the use of dyn or impl may depend on the exact details of the function and the user's needs. If a function requires a specific type, and its implementation is important for the function, impl may be more appropriate. However, if the function requires a certain behavior that can be provided by multiple types, dyn may be more suitable because it provides the user with more flexibility in the choice of type.
      It is important to understand the implications of impl and dyn and base the choice on the specific needs of the situation. In some cases, the use of impl may result in better outcomes, while in other cases, dyn may be more suitable.”

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

    Good video

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

    7:55 you could simply use a Trait Alias, since the Amphibious Trait has no methods (trait Amphibious = LandCapable + WaterCapable;)

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

    Best thing I have learned today.
    super traits. for that reason, I subscribe,

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

    You are correct in that rust does not consider itself object orienyed, as rust consideres object orientation an antipattern. Rust olis functional/procedural.

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

      Some would argue that using polymorphism is "object oriented programming". I think the lines are a bit gray here.

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

      “Objects” are no different than structs in Rust. You’ve got a memory region with a set of data in it. You’ve got a collection of operations the compiler will allow you to perform on that region. There is nothing special about objects.

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

      The conversation behind classes and inheritance is different. But to associate “objects” with those ideas is IMO wrong.

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

    Good video. Why the switch to emacs? Also random note in case you've never seen it, Control-l will clear the terminal screen without having to type clear.

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

      thanks! I had been using VSCode just for the videos because it seemed like thats what most of the viewers are using, while using neovim behind the scenes. I switched to doom emacs and decided I really liked it, and haven't felt especially compelled to switch back to neovim. Shortly thereafter I decided to try using emacs in the videos as I figured it probably would't bother the VSCode folks - hopefully that is indeed the case 🙃
      Thanks for the Ctrl-I tip, I'm constantly finding gaping holes like this in my knowledge of shortcuts!

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

      @@codetothemoon only the code matters, not the editor you use, so keep using whatever editor you'd like, doesn't bother us

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

      @@codetothemoon Makes sense. I think they've all looked great in the videos.

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

    I emitted quite a strange noise at the clip art of somebody washing a circuit board

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

    Woah, how does your "cargo run" compile it in 0.11s? I just got mine to compile a trivial program in 2.5s instead of 4.5s by changing the linker. (This was in WSL2.) Now that I know it CAN be fast, I want to make it that fast! 2 seconds is long enough to get bored...

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

      Not sure, I haven't done anything to deliberately make it faster. I am on a 1 year old M1 macbook pro, not sure if it's just because of the hardware

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

      @@codetothemoon Thanks anyway - when I saw that compilation can be fast, I went searching for answers. It turns out that WSL2 was indeed my problem: accessing files from the NTFS side is quite slow. (It doesn't normally feel THAT slow, but I guess cargo or rustc accesses a LOT of files.) The solution is to move the source files to the Linux filesystem, or run the Rust compiler on Windows. VS Code can edit the files inside WSL, too.
      Btw, here's a hint for you, when you use rust-analyzer with VS Code: it shows the inferred types of local variables by default, but those can be hidden, as well as function parameter names. I find those to be spammy and super distracting, and I can get the same info if I need it, by hovering over the text :)

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

    2nd interesting thanks

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

    Took me a while to notice that you are using doom emacs

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

      indeed, I've been pretty happy with it lately

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

      @@codetothemoon Your video on helix made me try it. Any plans to cover doom emacs in a future video?

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

    Gosh I really thought you were the typing god himself until I realized that it’s sped up

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

    As soon as i saw you copy pasting the drive method. I screamed 'USE A TRAIT!!'

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

      hah, you knew what was coming!

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

    Which theme is that? 😮

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

    Its like inheritance had composition had a baby but composition had stronger genetics.

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

      LOL that's a very good description of the approach Rust takes 😎

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

      @@codetothemoon I'm not a rust developer but i just realized ive been subconsciouslly learning Rust through your videos. It now feels less intimidating, thank you so much for sharing your knowledge with us.

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

    providing code would be nice

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

    Very nice! Now do trait objects.

    • @youseft.3141
      @youseft.3141 ปีที่แล้ว +2

      that is what dyn are

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

    I really thought Emacs has gone extinct, but it seems to have one last user.

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

      Lol 😂 I’m definately not one of those folks who is married to their editor, give me an alternative that has org mode and supports multiple fonts in the same buffer and I’ll consider switching 🙃

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

      @@codetothemoon I definitely am one of those, but I've chosen the only good and bright side there is. 🤣

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

      @@befosocial you're referring to Notepad I'm assuming? 😎

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

    Please consider facilitating object oriented programming in other languages. Rust should be used in a more functional style.
    Having said that, it was a very good explanation! Thank you!
    Btw, C++ does not have generics.

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

      Rust's traits system *is* based on some OO ideas. I don't understand what you're trying to achieve by abstaining from Rust's premier construct for polymorphism. The language is clearly multiparadigm and you're only going to end up writing non-idiomatic code if you're in denial of that.
      Your comment about C++ also doesn't make sense. A project like STL was authored in C++ specifically because it had the best generics support you could get in a systems language at that time, even though STL's author preferred functional over the other paradigms.
      STL is also based on OO ideas, excluding inheritence. Of the OO ideas Rust took from C++, an STL inspired standard library and traditional oo single dispatch, which the traits system uses, come to mind. Rust is oo for the same reason C++ is, it just makes sense to encapsulation remaining state when you're done with the functional and pure part of your program. This is a natural evolution of systems languages that also target the application realm. I don't think there's any value in denying this.

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

      The hive mind doesn’t know what they’re talking about at this point. What is special about an “object” in C++ vs a struct instance in Rust? Answer: nothing. An object is just a set of data in memory that can have certain operations performed on it. A struct instance if just a set of data in memory that can have certain operations performed on it. There is nothing special about “objects”.
      Using polymorphism has nothing to do with “object orientation”. Rust’s enums, traits, and generics all work with “objects” but those are premier features of the language.
      You can’t write any code without having complex structured sets of data and defined operations for them. These are objects. People see “OOP” and “Rust” in the same sentence and their brain cells dissolve.

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

    bruh i tought rust now driven by NATO

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

    You type hella fast

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

      that fast forward makes me look like a competent typer!

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

    If the lake is frozen, why would we need to float ? ;p

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

    Not having inheritance somewhat inclines me to consider other programming languages. There are numerous design patterns that work effectively with inheritance. Additionally, in other programming languages, I can utilise both inheritance and composition, as well as abstract classes and interfaces. Therefore, why would I want to relinquish such flexibility for the sake of using a niche programming language like Rust, merely due to its hype? No thanks.

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

    ctrl+l (L not i) clears the terminal. you don't have to type clear in full

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

      thanks for the tip! i have some gaping holes in my knowledge of shortcuts. Getting tips like this is one of the things I like most about uploading videos 😎

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

    My main takeaway....English doesn't have a general verb to describe a travelling boat! There's 'to sail', but nothing more general. Luckily Nelson died before having to command engine driven boats. Or did he?

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

    Since when is Rust object-oriented? I thought it was a procedural language with functional bits.

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

      It's not a class-based OOP language, but that's not an absolute requirement to be considered OO.

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

    first one here

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

    But.... Rust isn't object oriented, and you shouldn't treat it as such, nor do you need it to be.

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

      What is your definition of object oriented?

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

    Looks a little bit cumbersome to me in Rust. No implicit self? Same like in Python? Aaaaaaah ... that's a bummer for me. `dyn` is explicit but also cumbersome. Explicit but not very succinct.

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

    13 And no man hath ascended up to heaven, but he that came down from heaven, even the Son of man which is in heaven.
    14 And as Moses lifted up the serpent in the wilderness, even so must the Son of man be lifted up:
    15 That whosoever believeth in him should not perish, but have eternal life.
    16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life.
    17 For God sent not his Son into the world to condemn the world; but that the world through him might be saved.
    18 He that believeth on him is not condemned: but he that believeth not is condemned already, because he hath not believed in the name of the only begotten Son of God.
    19 And this is the condemnation, that light is come into the world, and men loved darkness rather than light, because their deeds were evil.
    20 For every one that doeth evil hateth the light, neither cometh to the light, lest his deeds should be reproved.
    21 But he that doeth truth cometh to the light, that his deeds may be made manifest, that they are wrought in God.
    (Jn.3:13-21)

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

      Moses and Jesus both likely implement the Prophet trait, which presumably contains a teach method! They are certainly not polytheistic, but could be viewed as polymorphic...

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

      @@codetothemoon
      14 And the Word was made flesh, and dwelt among us, (and we beheld his glory, the glory as of the only begotten of the Father,) full of grace and truth.
      15 John bare witness of him, and cried, saying, This was he of whom I spake, He that cometh after me is preferred before me: for he was before me.
      16 And of his fulness have all we received, and grace for grace.
      17 For the law was given by Moses, but grace and truth came by Jesus Christ.
      18 No man hath seen God at any time; the only begotten Son, which is in the bosom of the Father, he hath declared him.
      (Jn.1:14-18)
      39 Search the scriptures; for in them ye think ye have eternal life: and they are they which testify of me.
      (Jn.5:39)
      46 For had ye believed Moses, ye would have believed me: for he wrote of me.
      (Jn.5:46)
      45 Philip findeth Nathanael, and saith unto him, We have found him, of whom Moses in the law, and the prophets, did write, Jesus of Nazareth, the son of Joseph.
      46 And Nathanael said unto him, Can there any good thing come out of Nazareth? Philip saith unto him, Come and see.
      47 Jesus saw Nathanael coming to him, and saith of him, Behold an Israelite indeed, in whom is no guile!
      48 Nathanael saith unto him, Whence knowest thou me? Jesus answered and said unto him, Before that Philip called thee, when thou wast under the fig tree, I saw thee.
      49 Nathanael answered and saith unto him, Rabbi, thou art the Son of God; thou art the King of Israel.
      50 Jesus answered and said unto him, Because I said unto thee, I saw thee under the fig tree, believest thou? thou shalt see greater things than these.
      51 And he saith unto him, Verily, verily, I say unto you, Hereafter ye shall see heaven open, and the angels of God ascending and descending upon the Son of man.
      (Jn.1:45-51)

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

      And the first beast was like a lion,
      and the second beast like a calf,
      and the third beast had a face as a man,
      and the fourth beast was like a flying eagle.
      (Rev.4:7)
      The four animals describe the four traits of Jesus :)

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

    video is flashy and bad, dislike

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

      Thanks for the feedback! What else didn’t you like aside from the flashiness?