Rust Powered Polymorphism ⚡️ With Traits

  Переглядів 87,206

Code to the Moon

Code to the Moon

Рік тому

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
@Possseidon
@Possseidon Рік тому
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 Рік тому
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 Рік тому
@@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 Рік тому
oh man, every day, after 5 years, I still learn something new about Rust.
@JorgetePanete
@JorgetePanete Рік тому
gone*
@ythanzhang
@ythanzhang Рік тому
You can also make T ?Size so it works on trait objects too. impl C for T {}
@mk72v2oq
@mk72v2oq Рік тому
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 Рік тому
very true, good point! ditching inheritance makes code infinitely more readable imo...
@phenanrithe
@phenanrithe Рік тому
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 Рік тому
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 Рік тому
@@phenanrithe Can you give examples? It would help
@ozanmuyes
@ozanmuyes Рік тому
Is Rust even an object-oriented language?
@Julian-vi4vl
@Julian-vi4vl Рік тому
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
@narigoncs
@narigoncs Рік тому
Worth mentioning that `impl Trait` is just syntax sugar for `fn road_trip(vehicle: &T) {}`
@BulbaWarrior
@BulbaWarrior Рік тому
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 Рік тому
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 Рік тому
@@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 Рік тому
@@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
@markolsson2740
@markolsson2740 Рік тому
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 Рік тому
WOW thank you so much Mark!! I really appreciate your support and your kind words. Thanks again for watching!
@marcusrehn6915
@marcusrehn6915 Рік тому
This feels like a far superior way to do OOP than what I am used to see in other languages.
@codetothemoon
@codetothemoon Рік тому
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++?
@cd-bitcrshr
@cd-bitcrshr Рік тому
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.
@sergiuoanes4635
@sergiuoanes4635 Рік тому
Absolutely love your videos. Simple examples straight to the point. Keep them coming! thanks
@codetothemoon
@codetothemoon Рік тому
wow thank you so much for your support and kind words! more to come!
@Kodlak15
@Kodlak15 Рік тому
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 Рік тому
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.
@fayaz2956
@fayaz2956 Рік тому
Whoa!! the way you explained the zero cost abstraction is mind blowing!!
@aditeya1024
@aditeya1024 Рік тому
I was writing a ray tracer in rust and this video was super helpful in explaining a trait!
@codetothemoon
@codetothemoon Рік тому
nice, really happy that it helped! and props to you for tackling a ray tracer, that's quite an undertaking!
@Redditard
@Redditard Рік тому
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)
@johndavidson8096
@johndavidson8096 Рік тому
Amazing video. You break down these rust concepts better than anyone else! Much appreciated as a TS/JS dev!
@anuradhaamarasinghe9649
@anuradhaamarasinghe9649 Рік тому
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!
@alfredomenezes8814
@alfredomenezes8814 Рік тому
Very nice video, I love your Rust content, keep going!
@kippie80
@kippie80 Рік тому
Didn't realize &impl and &dyn were so interchangeable, thanks!
@codetothemoon
@codetothemoon Рік тому
nice, glad you found it valuable!
@phenanrithe
@phenanrithe Рік тому
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).
@Xerofull
@Xerofull Рік тому
I like your video style, its getting better with each one +1
@ukaszlampart5316
@ukaszlampart5316 Рік тому
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.
@codetothemoon
@codetothemoon Рік тому
great point!
@janbaumann7794
@janbaumann7794 Рік тому
Really appreciate these videos. Keep up the good work :)
@codetothemoon
@codetothemoon Рік тому
wow thank you so much for the support Jan!!! more to come!
@creativecraving
@creativecraving 3 місяці тому
This video helped me understand the difference between the dyn and impl syntax. Thank you!
@codetothemoon
@codetothemoon 3 місяці тому
nice, really happy you got something out of it!
@nsgirish
@nsgirish 11 місяців тому
excellently explained
@codetothemoon
@codetothemoon 11 місяців тому
thank you, glad you liked it!
@rct999
@rct999 4 місяці тому
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!
@2002budokan
@2002budokan 6 місяців тому
Excellent small examples.
@codetothemoon
@codetothemoon 6 місяців тому
Thank you! 🙏
@YuruCampSupermacy
@YuruCampSupermacy Рік тому
loved the video, keep making more
@codetothemoon
@codetothemoon Рік тому
thanks! more to come!
@Feyon
@Feyon Рік тому
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 місяці тому
amazing video. thank you so much!
@codetothemoon
@codetothemoon 2 місяці тому
thanks, really happy you liked it!
@GlobalYoung7
@GlobalYoung7 Рік тому
thank you 👍⚡️
@codetothemoon
@codetothemoon Рік тому
thanks for watching!
@ericleijonmarck
@ericleijonmarck Рік тому
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!
@grahamcracker1234
@grahamcracker1234 Рік тому
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
@joshuarose3186
@joshuarose3186 5 місяців тому
Hi there, i was wondering if you had a link to your dotfiles? Reason being, I love the way your emacs looks.
@johnbaxter7582
@johnbaxter7582 Рік тому
cool quick tutorial, just found out about dyn and impl
@codetothemoon
@codetothemoon Рік тому
thanks glad you got something out of it!
@Panakotta000
@Panakotta000 Рік тому
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...
@jm-alan
@jm-alan Рік тому
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 Рік тому
nice, really glad you got something out of the video, despite likely already being familiar with many of the concepts!
@user-bt8tg7ct4i
@user-bt8tg7ct4i 7 місяців тому
very nice
@codetothemoon
@codetothemoon 7 місяців тому
thank you!
@GlobalYoung7
@GlobalYoung7 Рік тому
thank you
@codetothemoon
@codetothemoon Рік тому
wow thank you so much for your support!!!!
@adicide9070
@adicide9070 8 місяців тому
I think I missed the twist :D was it the impl vs dyn? :)
@ReedoTV
@ReedoTV Рік тому
Had no idea super traits were a thing!
@codetothemoon
@codetothemoon Рік тому
nice, love it when folks who already know about the video topic are still able to get value!
@ReedoTV
@ReedoTV Рік тому
@@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.
@BvngeeCord
@BvngeeCord Рік тому
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?
@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.
@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?
@danielgerlach5141
@danielgerlach5141 Рік тому
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 Рік тому
The editor is doom emacs.
@codetothemoon
@codetothemoon Рік тому
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 Рік тому
@@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
@guilherme5094
@guilherme5094 Рік тому
👍Thanks!
@codetothemoon
@codetothemoon Рік тому
thanks for watching!
@mvargasmoran
@mvargasmoran Рік тому
like your style.
@codetothemoon
@codetothemoon Рік тому
Thanks, much appreciated!
@yondaime500
@yondaime500 Рік тому
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 Рік тому
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 Рік тому
@@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 Рік тому
@@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.
@barefeg
@barefeg Рік тому
Would it be possible to implement amphibious directly without having to implement lang capable and water capable?
@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.
@JosephDalrymple
@JosephDalrymple Рік тому
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 Рік тому
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.
@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
@hos7012
@hos7012 Рік тому
thx for your effort what keyboard and IDE do u use?
@codetothemoon
@codetothemoon Рік тому
thanks for watching! Keyboard is Corne v3 and IDE is DOOM Emacs
@basalticlife1861
@basalticlife1861 Рік тому
thank you, that was easy to understand.
@codetothemoon
@codetothemoon Рік тому
thanks, glad you liked the format!
@rGxDale
@rGxDale 9 місяців тому
What editor and theme is that? its fkin beautiful
@bhavyakukkar
@bhavyakukkar 3 місяці тому
doom emacs, monokai-classic
@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.
@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.
@ozanmuyes
@ozanmuyes Рік тому
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!
@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-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?
@nirajgautam403
@nirajgautam403 3 місяці тому
Can we use vars from base struct in derived one?
@DrumMeister
@DrumMeister Рік тому
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 Рік тому
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 місяців тому
Good video
@codetothemoon
@codetothemoon 11 місяців тому
thank you!
@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.
@Erhannis
@Erhannis 8 місяців тому
I emitted quite a strange noise at the clip art of somebody washing a circuit board
@chris.davidoff
@chris.davidoff Рік тому
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 місяців тому
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)
@Taurdil
@Taurdil Рік тому
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.
@xenocampanoli815
@xenocampanoli815 4 місяці тому
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).
@DaddyFrosty
@DaddyFrosty Рік тому
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 Рік тому
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 Рік тому
@@codetothemoonfair enough 👍
@handsanitizer2457
@handsanitizer2457 Рік тому
2nd interesting thanks
@codetothemoon
@codetothemoon Рік тому
glad you liked it!
@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.
@MTrax
@MTrax 2 місяці тому
Gosh I really thought you were the typing god himself until I realized that it’s sped up
@renxula
@renxula Рік тому
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 Рік тому
@@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 :)
@TheToric
@TheToric Рік тому
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 Рік тому
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.
@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,
@razvbir
@razvbir Рік тому
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?
@jrmoulton
@jrmoulton Рік тому
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 Рік тому
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 Рік тому
@@codetothemoon only the code matters, not the editor you use, so keep using whatever editor you'd like, doesn't bother us
@jrmoulton
@jrmoulton Рік тому
@@codetothemoon Makes sense. I think they've all looked great in the videos.
@pixelstriko1642
@pixelstriko1642 Рік тому
As soon as i saw you copy pasting the drive method. I screamed 'USE A TRAIT!!'
@codetothemoon
@codetothemoon Рік тому
hah, you knew what was coming!
@football-is-divine
@football-is-divine 4 місяці тому
Which theme is that? 😮
@bhavyakukkar
@bhavyakukkar 3 місяці тому
monokai
@larrymarso4492
@larrymarso4492 Рік тому
Very nice! Now do trait objects.
@youseft.3141
@youseft.3141 Рік тому
that is what dyn are
@raphaeljaggerd3585
@raphaeljaggerd3585 10 місяців тому
Its like inheritance had composition had a baby but composition had stronger genetics.
@codetothemoon
@codetothemoon 10 місяців тому
LOL that's a very good description of the approach Rust takes 😎
@raphaeljaggerd3585
@raphaeljaggerd3585 9 місяців тому
@@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
@befosocial
@befosocial Рік тому
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 Рік тому
@@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? 😎
@brunomello7499
@brunomello7499 Рік тому
You type hella fast
@codetothemoon
@codetothemoon Рік тому
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.
@aryabp
@aryabp Рік тому
bruh i tought rust now driven by NATO
@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 Рік тому
Since when is Rust object-oriented? I thought it was a procedural language with functional bits.
@peter9477
@peter9477 Рік тому
It's not a class-based OOP language, but that's not an absolute requirement to be considered OO.
@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 Рік тому
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.
@NikolajLepka
@NikolajLepka Рік тому
ctrl+l (L not i) clears the terminal. you don't have to type clear in full
@codetothemoon
@codetothemoon Рік тому
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 😎
@justsomerandomguyman
@justsomerandomguyman Рік тому
But.... Rust isn't object oriented, and you shouldn't treat it as such, nor do you need it to be.
@codetothemoon
@codetothemoon 11 місяців тому
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.
@wateenafzal2963
@wateenafzal2963 Рік тому
first one here
@codetothemoon
@codetothemoon Рік тому
nice!
@olsuhvlad
@olsuhvlad Рік тому
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 місяців тому
video is flashy and bad, dislike
@codetothemoon
@codetothemoon 10 місяців тому
Thanks for the feedback! What else didn’t you like aside from the flashiness?
Rust Interior Mutability - Sneaking By The Borrow Checker
16:02
Code to the Moon
Переглядів 62 тис.
but what is 'a lifetime?
12:20
leddoo
Переглядів 55 тис.
Using Trait Objects in Rust
13:32
Let's Get Rusty
Переглядів 36 тис.
All Rust features explained
21:30
Let's Get Rusty
Переглядів 272 тис.
Философия Unsafe Rust
22:35
Bitωise
Переглядів 4,2 тис.
The Dygma Defy: A Software Developer's Dream?
8:16
Code to the Moon
Переглядів 52 тис.
The Flaws of Inheritance
10:01
CodeAesthetic
Переглядів 872 тис.
Rust Data Modelling Without Classes
11:25
No Boilerplate
Переглядів 156 тис.
Larger Scale Software Development (and a Big Trap)
17:17
Code to the Moon
Переглядів 89 тис.
Rust is not a faster horse
11:37
No Boilerplate
Переглядів 314 тис.
i tried so many keyboards - this is the one
23:37
Code to the Moon
Переглядів 111 тис.
Rust's Witchcraft
9:18
No Boilerplate
Переглядів 168 тис.
How much charging is in your phone right now? 📱➡️ 🔋VS 🪫
0:11
The power button can never be pressed!!
0:57
Maker Y
Переглядів 38 млн
📱 SAMSUNG, ЧТО С ЛИЦОМ? 🤡
0:46
Яблочный Маньяк
Переглядів 615 тис.