Building a space station in Rust

  Переглядів 90,979

No Boilerplate

No Boilerplate

Рік тому

Watch Lost Terminal here: lostterminal.com/
This video shows you how to build simple Rust programs, starting with your data model.
If you would like to support what I do, I have set up a patreon here: / noboilerplate Thank you!
All my videos are built in compile-checked markdown, transcript sourcecode available here github.com/0atman/noboilerplate
If you would like to support me, you can get special Discord benefits here / noboilerplate
Corrections are in the pinned ERRATA comment.
Start your Rust journey here: doc.rust-lang.org/stable/book/
PROMO
My name is Tris Oaten and I produce fast, technical videos.
Follow me here / 0atman
Website for the show: noboilerplate.org
Come chat to me on my discord server: / discord
If you like sci-fi, I also produce a hopepunk podcast narrated by a little AI, videos written in Rust! www.lostterminal.com
If urban fantasy is more your thing, I also produce a podcast of wonderful modern folktales www.modemprometheus.com
CREDITS
Special thanks to my patreon sponsors:
- Affax
And to all my patrons!

КОМЕНТАРІ: 278
@NoBoilerplate
@NoBoilerplate Рік тому
ERRATA - 0:43 This is not how format strings look - sorry! It compiles but doesn't do what I wanted. - 1:07 misspelled "California" - 2:15 duplicate variable name "rand_int", it should of course be "rand_float" - Because randomising sections can cause duplicates, your searching will find the FIRST instance of the section, not necessarily the one you want. The fix for this is left as an exercise for the viewer, and future me, apologies! - 7:00 thanks to everyone who said that `iter.find()` would be perfect for this job! - Thread panic on station breakdown reported by @Mitch557. Logic bug in my game loop, but unrelated to the type system demo github.com/0atman/noboilerplate/issues/9
@KyraKrassenburg
@KyraKrassenburg Рік тому
dont forget to pin this comment ;)
@NoBoilerplate
@NoBoilerplate Рік тому
@@KyraKrassenburg omgggggg youtube LOVES unpinning it when I edit - THANK YOU!
@KyraKrassenburg
@KyraKrassenburg Рік тому
@@NoBoilerplate haha i didnt realise thats what happened.. thats odd lol
@xanri7673
@xanri7673 Рік тому
0:42 formatting uses single brackets, you can't put arbitrary expressions inside the brackets, and the method should take &self, not self.
@Adrian-ql5yz
@Adrian-ql5yz Рік тому
It was removed from pin once again.
@zyansheep
@zyansheep Рік тому
Hey look ma, No Boilerplate uploaded again!
@NoBoilerplate
@NoBoilerplate Рік тому
I'm as excited as you are!
@Sourcecodemastergoaheadcheater
@Sourcecodemastergoaheadcheater 2 місяці тому
😂😂 hi ma I'm a underrated semi-famous coder 😂😂❤❤
@tylerbloom4830
@tylerbloom4830 Рік тому
A favorite pattern of mine is the free generic. Say you have several objects with ids that are all the same underlying type, such as Uuid. You can have a type, say TypedId(pub Uuid, PhantomData). This is generic over your structs and only holds PhantomData for the free generic. It is no larger than a Uuid, but now, you can't mistake a Station id for a Section id!!! This is better than `StationId(pub Uuid)` because you only have to implement things once while still getting type safety!!
@NoBoilerplate
@NoBoilerplate Рік тому
now that is COOL!
@ArrekinWorks
@ArrekinWorks Рік тому
Could you post a small working example?
@tylerbloom4830
@tylerbloom4830 Рік тому
​@@ArrekinWorks ​ ​ Absolutely! In the example, I've also included a link to a project where I'm using this, in case you want a "real world" example. Note: UKposts doesn't like me posting links, so go to the Rust playground and add gist=34f765f98445ca4c2e8da6fbab6a53f8 to the URL​
@ArrekinWorks
@ArrekinWorks Рік тому
@@tylerbloom4830 Amazing, Thank you! I'm still early in my days of learning Rust but I already hit this issue with having one type as id for different structs that should not be treated as one type and so far I used structs `Alias(pub IdType)`. I didn't know about PhantomData, so thank you for the larger snippet :)
@tylerbloom4830
@tylerbloom4830 Рік тому
@@ArrekinWorks No problem! I was doing the same thing for a while too! What I really wanted was a transparent wrapper. Uuid implements lots of neat stuff, and I'd prefer not to write the boilerplate for it all. But Defer will have to suffice.
Рік тому
From "you can use rust to make your life simpler" to "LETS BUILD A SPACE STATION" I like where this is going!
@NoBoilerplate
@NoBoilerplate Рік тому
TO THE MOON!
@w1keee
@w1keee Рік тому
@@NoBoilerplate come to think of it, rust would be perfect for infrastructure on the moon!
@notdumbrella6399
@notdumbrella6399 8 місяців тому
@@w1keee And the Mars
@clayhudson8892
@clayhudson8892 Рік тому
Im running into an issue where i watch one of your videos to learn about rust and then i wake up 2 hours later because your videos and voice are so peaceful that i drifted off into an afternoon nap. Thanks for making great content.
@NoBoilerplate
@NoBoilerplate Рік тому
I'll take that as a complement! If you want actual relaxing content in my voice, I'd love to know what you think of my sifi, hopepunk podcast, Lost Terminal ukposts.info/have/v-deo/qGOTeHtwoqmrrpc.html
@erikyoung5139
@erikyoung5139 9 місяців тому
@@NoBoilerplate I use it for this precise purpose.
@NoBoilerplate
@NoBoilerplate 9 місяців тому
@@erikyoung5139 thank you!
@w1keee
@w1keee Рік тому
the unrepresantability of invalid states is one of my favourite rust features. i hope the devs add ranged integers soon!
@NoBoilerplate
@NoBoilerplate Рік тому
There's already crates that do this, get to it!
@Rudxain
@Rudxain Рік тому
Exactly what I was thinking!
@r.pizzamonkey7379
@r.pizzamonkey7379 Рік тому
@@NoBoilerplate It does kind of feel like the sort of thing that wouldn't be out of place in std, especially since the compiler could definitely use them as an optimization hint.
@Singhrager
@Singhrager Рік тому
I don't have a use case that really requires me to use Rust, but hell, you've gone and made it impossible to resist. I just dropped everything I was doing to watch this and was not disappointed. Bravo!
@NoBoilerplate
@NoBoilerplate Рік тому
Things you can do in Rust: Frontend web dev with yew.rs backend web dev with rocket.rs game dev with bevy Bare-metal coding with many no-std crates!
@lardosian
@lardosian Рік тому
@@NoBoilerplate Desktop apps with Tauri, crypto with Solana..
@NoBoilerplate
@NoBoilerplate Рік тому
@@lardosian Tauri isn't really Rust, I'd spend my days writing my javascript app INSIDE Tauri, right?
@lardosian
@lardosian Рік тому
@@NoBoilerplate Have not actually used Tauri, just heard about it recently.
@NoBoilerplate
@NoBoilerplate Рік тому
@@lardosian Yeah, I got quite excited about it as they went 1.0 recently right? However if you look into it, it's an electron clone. A REALLY GOOD ONE, faster and more secure, but you still write your app in web technologies. Not a bad thing, per se, but I'm hardly looking forward to maintaining another js project...!
@daskadse769
@daskadse769 Рік тому
7:04 I'd do something like this: if let Some(sec) = station.sections.iter_mut().first(|m| m.name == section) { sec.active = true; } If you'd like to panic on not finding it, just else-block panic or use match instead. Alternatively, you could just use .for_each(), as Options are iterable themselves. That way you could also easily change from .first() to .filter() if behavior is desired where multiple matches were possible.
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you!
@Betacak3
@Betacak3 Рік тому
To panic after not finding the section you could also do this: let broken_section = station.sections.iter_mut().find(...).expect("Section not found."); broken_section.active = true; Or alternatively this, if you like doing things in a single statement: station.sections.iter_mut().find(...).map(|sec| { sec.active = true; }).expect("Section not found."); But I'd personally prefer the first one.
@NoBoilerplate
@NoBoilerplate Рік тому
@@Betacak3 Nice, that's much better than indexing!
@feathecutie9942
@feathecutie9942 Рік тому
This video just made me so unexplainably happy ^-^ Both because of the amazing technical aspects and the beauty of rust you showcased, but also because of being reminded of Sev through the topic and your voice after having absolutely fallen in LOVE with Lost Terminal the past few days
@NoBoilerplate
@NoBoilerplate Рік тому
I'm so pleased! Thank you! LT is my favourite thing in the WORLD!
@martinbecker1069
@martinbecker1069 Рік тому
I felt much in the same way as you do when I was building a personal tool. I found the `From` trait was extremely helpful in defining how to move from one Type to another, because once I'd done it for all possible types I was using, most of my code was just calling `.into()` and it ended up looking like a flow of data transforming from one state into another. A nice side-effect is that almost all of you're logic that handles transforms between Types are easily located in single places (where ever you implemented the `From` trait) so it's all easy to find.
@NoBoilerplate
@NoBoilerplate Рік тому
That's a great tip, thank you!
@messester7675
@messester7675 Рік тому
This is an amazing guide on how to structure software in general. I have trouble telling my friends and explaining to them how to nicely structure software, and this is an excellent guide. Please make more guides like this because even if only for rust they make for stunning teaching tools.
@NoBoilerplate
@NoBoilerplate Рік тому
Well thank you so much! I plan to write a video on Rust modules in a similar way soon!
@ShreksSpliff
@ShreksSpliff Рік тому
Love your content! Turn audio compression down, the unnatural sound is diatracting. Device speakers will compress your voice. Users using earphones won't need the compression. Also pushing less air into consonants and more into vowels will do your delivery wonders. You've got a great voice for what you love doing. Keep it up and thank you!
@NoBoilerplate
@NoBoilerplate Рік тому
Thanks for the tips Wayne, always appreciated. Could you give me specific timecodes for the problems you're mentioning? Thank you!
@BenjaminBrienen
@BenjaminBrienen Рік тому
@@NoBoilerplate I'm not sure what he's referring to. The only thing I noticed was a couple mouth sounds, which is fixed by moving farther from the microphone. Wasn't really a bother, though. Great video! I'm excited to see more specific examples of ways rust has empowered you to write software in a more provable and less guess-and-check way.
@dardevelin
@dardevelin Рік тому
@@NoBoilerplate The voice and cadence is literally a + in my opinion.
@NoBoilerplate
@NoBoilerplate Рік тому
@@dardevelin Thank you so much! I just wrapped season 9 of Lost Terminal - I've had a LOT of practice! ukposts.info/have/v-deo/qGOTeHtwoqmrrpc.html
@ottergauze
@ottergauze Рік тому
I just came across this channel and, wow, it has completely revitalised my drive to make stuff in Rust.
@NoBoilerplate
@NoBoilerplate Рік тому
Mission accomplished. The language is incredible, as I try to show in my videos. start here fasterthanli.me/articles/a-half-hour-to-learn-rust then hit the book, and come talk to the community on the discord server (links on noboilerplate.org)
@seubmarine5347
@seubmarine5347 Рік тому
Wake up babe. New No Boilerplate video just dropped.
@NoBoilerplate
@NoBoilerplate Рік тому
I'm as excited as you are!
@Yotanido
@Yotanido Рік тому
The type state pattern is also incredibly useful here. Things like keeping track of whether a file descriptor is open or closed in the type, or making a builder that requires certain values to be set, is very useful. Admittedly, code that makes heavy use of this looks terrible, though. (For the implementation - the API that results from it is very neat :D)
@NoBoilerplate
@NoBoilerplate Рік тому
thank you so much for telling me this, I now have a name for the pattern!
@darrennew8211
@darrennew8211 Рік тому
@@NoBoilerplate Tyestate is the part of Hermes that Rust took to make the borrow checker. When the full thing is built directly into the language, it becomes much easier to read everything. Hermes somewhat over-used it, but it would be nice if more languages incorporated it directly.
@rotteegher39
@rotteegher39 Рік тому
I was watching your podcast even before this video came out!
@NoBoilerplate
@NoBoilerplate Рік тому
A Day #1 fan! Thank you so much, I love writing Rust videos, but Lost Terminal is the work I'm most proud of :-)
@fallout__boy1130
@fallout__boy1130 Рік тому
Just discover this channel yesterday. This is really nice content, your voice is pleasing to listen to!
@NoBoilerplate
@NoBoilerplate Рік тому
Oh have I got good news for you, there's 9 seasons of me narrating Lost Terminal so far, I'd love to know what you think! ukposts.info/have/v-deo/qGOTeHtwoqmrrpc.html
@dedenapraia
@dedenapraia Рік тому
Amazing Video !, Thank you very much for giving away this presentation. As a Rust newbie (Coming from high level languages) this kind of explanations are very useful to change the traditional mindset and think in a "Rusty" way. Looking forward for more Videos !. thanks again
@NoBoilerplate
@NoBoilerplate Рік тому
Super! I've also come from high-level languages. I have made a few of these, check out the playlist here and let me know what you think! ukposts.info/have/v-deo/iWNynLB_qG6gyKc.html
@eignnx_1738
@eignnx_1738 Рік тому
I love the crate suggestions! There are so many great crates out there I didn't even know I wanted
@NoBoilerplate
@NoBoilerplate Рік тому
I've not even SCRATCHED the surface! look at THIS crates.io/crates/no-panic
@Medik_0001
@Medik_0001 Рік тому
Love Cool Retro Term. I've also used it for videos myself, love to see it used here also!
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much! Did you see the podcast videos? ukposts.info/have/v-deo/qGOTeHtwoqmrrpc.html
@joserobjr7010
@joserobjr7010 Рік тому
Simply amazing!
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much!
@bmanturner
@bmanturner Рік тому
Instant subscribe. Great video. Informative, interesting and moderately brief
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much! Have you seen my other Rust videos, they're all packed with really cool Rust features, and moderately brief too :-D
@bmanturner
@bmanturner Рік тому
@@NoBoilerplate I'll be doing a deep dive before long. I smashed the bell for updates. Oh, Lost Terminal was really nice. It was clever and humorous and well written, and the music was great. I like how you've paired your passions.
@NoBoilerplate
@NoBoilerplate Рік тому
@@bmanturner Thank you so much! 9 seasons so far!
@Ehomer0815
@Ehomer0815 Рік тому
New rust video from tris.. instant like
@NoBoilerplate
@NoBoilerplate Рік тому
You're too kind!
@precumming
@precumming Рік тому
3:06 after functional experience I hate using something before defining. All of my programs you should be able to start on line 1 of the first file and read to the last line of the last file (most languages don't have an order of files but I make a note, so it's easier for me to come back to the project) and you will never come across a reference to something you have not seen the definition of. For instance let's say you have never seen the code before and you get to the struct and you see SectionName, you haven't seen that before so you then need to find where the definition is and read it before going backwards back to where you were, and you have to do this for every bit of data that references after the current line which can get annoying having to jump around constantly and it requires more work to understand something. I've had someone say to me that they like to have the main thing first because that's what someone reading will see and they will see the context of what some data is before seeing the definition - but to that I say that you have file names to tell you what is contained and then you have sensibly named data so that when it is all combined you should already have a good idea of how it is structured. The tradeoff is that you will be told about things that aren't immediately used that you will need to keep tabs on but that you never jump around. Also, my thoughts do start in the main body of the program and then they branch upwards until I reach an end and then I write it. I'm used to F# where the first time I run the program it may already be completely finished.
@NoBoilerplate
@NoBoilerplate Рік тому
Rust's the same, if it compiles it works! F# and Rust both take after Haskell in that regard. I don't think your 'using something before defining' problems scale well. As soon as you split up your app into multiple files (isn't that most non-trivial programs?) you're going to be jumping to definition anyway? It's a good rule per-file, but imports exist...
@Yotanido
@Yotanido Рік тому
Do you need to jump to StationName? It's the name of the station, clearly. If you aren't looking specifically into how names work in the codebase, you probably don't care about the actual implementation. Getting a high-level overview is usually more useful, so I am also of the opinion that the most important bits should come first. Define things top-down, if you will.
@Gendulf
@Gendulf Рік тому
If you're following the philosophy of making things easier to read because they're going to be read more than written, it makes sense to order things a little differently, namely putting interfaces and public things near the top, and implementation details further down. Sometimes this lines up, but not always. It feels "neater" to order things by how to compiler will need it, but humans are good at digging into things only when they need to.
@deer6413
@deer6413 10 місяців тому
I had a VERY similar idea for a game exactly like the one you talk about! Can't wait to give it a try!
@NoBoilerplate
@NoBoilerplate 10 місяців тому
Try out crates.io/crates/bracket-terminal for your simple game engine!
@aidensandbakken6648
@aidensandbakken6648 Рік тому
Note that while Java's type inference isn't as good as Rust's, it can perform type inference based on both sides of the assignment expression. To infer from the left side use the diamond operator: ArrayList foo = new ArrayList(); which is equivalent Rusts's let foo: Vec = Vec::::new(); and to infer from the right side use the var keyword: var foo = new Arraylist(); which is equivalent to Rust's let foo = Vec::::new(); Anyway, nice job on the videos, they're pretty good.
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much, and thank you for telling me about Java's ability. Using let/var isn't QUITE as nice as Rust though! ;-)
@SEOTADEO
@SEOTADEO Рік тому
Oh my god, this video is great!! I love you, this will save me a lot of trouble. Please make more videos on how to best write Rust Code. And your voice is one of the most charming ones to listen to, reminds me a lot of Sebastian Lague.
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much! If you'd like to listen more, you might like my scifi podcast Lost Terminal ukposts.info/have/v-deo/qGOTeHtwoqmrrpc.html
@SEOTADEO
@SEOTADEO Рік тому
@@NoBoilerplate Thanks for the hint! I'll listen to everything :)
@NoBoilerplate
@NoBoilerplate Рік тому
@@SEOTADEO Do comment as you go, I'd love to know your thoughts!
@tentaklaus9382
@tentaklaus9382 Рік тому
Tris you may enjoy a book called "Forever War" by Joel Haldeman. Thanks for inspiring me to keep going deeper with Rust, the struggle never stops ❤️
@NoBoilerplate
@NoBoilerplate Рік тому
You're right, it's on my bookshelf right now, loaned to me by a friend and ready to read. I will try to do so. I have a recommendation for you: The Spin Trilogy. Incredible stuff.
@costelinha1867
@costelinha1867 Рік тому
If he thinks this gives him super powers, wait till he finds out about Bevy's ECS, and how Structs can be used as components. (That is assuming he doesn't know it already, or that he's patient enough to sit trough it's compile times, I have a suspicion that he is.) (I'm also thinking of trying out macroquad, or the rust bindings for SDL. I was even considering building a ray casting engine in Rust, I mean sure a lot of my code will be from some tutorial, that I'd try to translate to Rust, but it might be fun...)
@NoBoilerplate
@NoBoilerplate Рік тому
LOVE Bevy!
@creeperkafasi
@creeperkafasi Рік тому
Thanks for another great video!
@NoBoilerplate
@NoBoilerplate Рік тому
My pleasure!
@barisbayrak
@barisbayrak Рік тому
Amazing content. Glad you exist.
@NoBoilerplate
@NoBoilerplate Рік тому
What a nice thing to say! You're very kind, thank you!
@AceofSpades5757
@AceofSpades5757 Рік тому
Fun and informative. Thanks!
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much! Did you see my other videos in this Rust series?
@AceofSpades5757
@AceofSpades5757 Рік тому
@@NoBoilerplate Yup, looks like almost all of them. I'll probably be checking out the couple I missed this afternoon.
@NoBoilerplate
@NoBoilerplate Рік тому
@@AceofSpades5757 How super, I'd love to hear what you think of them, if you fancy commenting on them.
@FelipeBalbi
@FelipeBalbi Рік тому
This was a very entertaining video 🙂 Thoroughly enjoyed
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much! There's 12 others in my rust series, I'd love to know what you think about the others!
@doormango
@doormango Рік тому
With Rust having so many powerful functional language features like immutability-by-default, first class functions, pattern matching, closures, iterators, and so on, surely it seems the safest Rust paradigm is to have no state at all?
@NoBoilerplate
@NoBoilerplate Рік тому
Love writing code like that, but now and then it's nice to have just a LITTLE state for some problems. I'm glad Rust is pragmatic so I can get work done - the real world is full of state!
@doormango
@doormango Рік тому
​@@NoBoilerplate I guess that is true. I also just learned that Rust does not (I stand to be corrected on this) have good native support for monads, which makes the whole stateless paradigm a lot more frustrating.
@NoBoilerplate
@NoBoilerplate Рік тому
@@doormango I'll have to trust you on that.
@ayoubboudouh7440
@ayoubboudouh7440 Рік тому
You do great work bro. Keep it up bro.❤❤
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much 😀
@gold15o2
@gold15o2 10 місяців тому
Why do you .expect on section repair when it is easy to assume that section could not be found? Is it really unexpected? Should we panic because of that? I'm asking out of curiosity, is it good approach or should we rather return some kind of error? (Rust newbie here)
@NoBoilerplate
@NoBoilerplate 10 місяців тому
Yes indeed, in a perfect world you don't have any paths that panic at runtime! Check my "rust on rails" video for a better demo of this feature
@user-wv1in4pz2w
@user-wv1in4pz2w Рік тому
7:00 I think you could use *station.section.iter_mut() .find(...) .expect(...) .active = true; or something like that.
@NoBoilerplate
@NoBoilerplate Рік тому
.find()! nice!
@Tigregalis
@Tigregalis Рік тому
@@NoBoilerplate Yep, if you look at the documentation e.g. for std:iter::Iterator, or one of the std::collections, you'll find these APIs where you thought you had to do it with two or three methods, or manually handling an index, but there's a method that lets you do it in one with no index required. Much of the time, clippy will pick these up for you too.
@NoBoilerplate
@NoBoilerplate Рік тому
@@Tigregalis no clippy help this time for me, I always run it! thank you!
@pup4301
@pup4301 Рік тому
For enums you could use the discriminant function if you want to know if a enum variant is the right variant you are looking for without describing them. You can also use type_name_of_val function if you want the name of the type but don't know the type name. It is in experimental though.
@NoBoilerplate
@NoBoilerplate Рік тому
oh cool, I'll look that up, thank you!
@pup4301
@pup4301 Рік тому
Welcome.
@devchaudhary78
@devchaudhary78 Рік тому
Nyc video, something unique thanks man❤️🙂
@NoBoilerplate
@NoBoilerplate Рік тому
My pleasure 😊
@Rudxain
@Rudxain Рік тому
0:43 I was wondering if Rust supports compile-time range constraints. What if we want Dogs to only have a maximum age of 30? A dog with age 128 is obviously not a Dog. What if I want the compiler the throw a compile error when a string doesn't match a constant regex? What if I want the compiler to show me a warning when it can't verify that an arbitrary String matches the regex? Raising exceptions when a value is invalid (while its type is correct) is usually done at runtime in most langs. I want to do that at compile-time
@PokeNebula
@PokeNebula Рік тому
couldnt this be done manually by writing another line of code with the assert macros?
@blucky_yt
@blucky_yt Рік тому
@@PokeNebula Assertion happens at runtime iirc, but you're on the right track, this could probably be implemented with macros
@sodiboo
@sodiboo Рік тому
Rust does not support arbitrary constraints about "this type but only these values" in its type system, or at least not directly in the form where the original type is clearly still there. However, const generics are very powerful! And so are macros! There is a crate for your use case with bounded integers, fittingly called bounded_integer. It has a BoundedU32 (and friends matching all of the other integer primitives including BoundedIsize) which takes a minimum and maximum value generically. For example, BoundedU8 if you want dogs to be only between 0 and 30 years old. There are some limitations to this approach though, and they don't implement Default among other things. The same crate also has a macro bounded_integer!() which allows you to create a new type which behaves pretty much the same, but macros are slightly more powerful and the type you get out of that will implement some more traits. You could, for example, create the dog age like so: bounded_integer! { pub struct DogAge { 0..=30 } }. I haven't actually used this crate so i don't know why it provides this "struct" form, because the other form of bounded_integer ! { pub enum DogAge { 0..=30 } } should behave the same, but the the enum form makes invalid states unrepresentable by its internal representation, so the compiler can use one of those invalid, out-of-range values to fit other things, so if you might not know the age of a dog, an Option will still be the same size. Also note the existence of std::num::NonZeroU8 and friends, which is basically a BoundedU8. The non-zero requirement is the most common range requirement as zero is a funky value for certain operations, and it can't be the denominator in a rational number for example. I think its actual use case and reason for being in stdlib is pointers though, and using similar tricks the compiler knows that a Box can never be null, and represents the None case in an Option as the null pointer. I'm getting carried away though, as this is for some specific optimization reasons and not for the semantic reason you wanted that "well, dogs don't live to hundreds of years", so let's go to the next thing. String regexes? Well, there's probably a crate out there for that. Several crates do basically the same thing (though not necessarily based on regexes) such as sqlx with compile-checked queries, and one that i've personally used is hex-literal, which i've used to convert color codes "#FF0000" into an Rgb([u8; 3]) for image processing. And if you've ever written any Rust, i can guarantee you've used println!(). The format string has to match a specific format described in std::fmt module-level documentation. The examples i've mentioned for strings all operate on string literals though, but you said "when it can't verify that an arbitrary String matches the regex". Well, no. The compiler doesn't do that. Not for the String type. But what you could do is create a newtype wrapping a String (perhaps even a Cow
@Rudxain
@Rudxain Рік тому
@@sodiboo lmao. Don't worry I like learning (and I sometimes also write/talk too much without noticing), I read the whole thing! I already knew about Path strings and OsString, but everything else was very helpful and interesting. Thank you. You should make a video about it, to spread information for other beginners
@flyingsquirrel3271
@flyingsquirrel3271 Рік тому
For your dog example the age would have to be known at compile time and not change at runtime. If that's the case, it could be a const generic and in that case there are hacky ways you can use to make compilation fail if it's not in a certain range, not a power of 2, or something like that.
@nellykantu8428
@nellykantu8428 Рік тому
You're amazing fr, wish i could code like u
@NoBoilerplate
@NoBoilerplate Рік тому
You're too kind: My code is not yet very good, I'm still learning Rust every day! What's your coding experience?
@nellykantu8428
@nellykantu8428 Рік тому
@@NoBoilerplate I'm still beginner, was learning Java but dropped it to learn rust
@NoBoilerplate
@NoBoilerplate Рік тому
@@nellykantu8428 Java's not a terrible option especially if you want to get paid! Take a look at the graph on this page, any language at the top right you'll be able to get paid work in, in my opinion: redmonk.com/sogrady/2022/03/28/language-rankings-1-22/ You can learn multiple language at once, too, don't forget! What's your goals, hobby or work?
@Wangstalol
@Wangstalol Рік тому
You absolute legend
@NoBoilerplate
@NoBoilerplate Рік тому
thank you!
@plato4ek
@plato4ek Рік тому
Hi! What is that `literate` program used to extract the source code in rust, and where can I find it?
@NoBoilerplate
@NoBoilerplate Рік тому
well spotted! It's a crate, just install it with `cargo install literate`! I'll update the readme
@the_kovic
@the_kovic Рік тому
While the possibility to use things in a place before you define them certainly feels convenient, as a reader of other people's code, I have learned to appreciate C and its requirement of linearity. I don't have to constantly jump around the code and nothing can ever surprise me because I know that if it's being used, I must have already seen it by the time it is used.
@NoBoilerplate
@NoBoilerplate Рік тому
Though I understand where this is coming from, it's only true in trivial programs. Once you start splitting up things into files, you lose this linearity of behaviour. However, on the whole, I agree that top-to-bottom reading makes absolute sense - the thing is that sometimes I just want to prototype something close to where I'm working, and then refactor it to the 'correct' position later.
@hussein7859
@hussein7859 Рік тому
this is amazing!
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you! I'm not even that good at Rust yet, but the type system has such POTENTIAL! I'll dig deeper in future videos as I figure it out myself!
@hussein7859
@hussein7859 Рік тому
@@NoBoilerplate Totally agree that type system has the potential to make the greatest language ever, please keep the great work! I started learning Rust because of your videos and I'm planning to rewrite my side project using it but still not confident enough 😅
@NoBoilerplate
@NoBoilerplate Рік тому
@@hussein7859 I'm so pleased! Do come and chat on my discord, ask any questions in #newbie-advice if you need!
@hussein7859
@hussein7859 Рік тому
@@NoBoilerplate I will, Thanks!
@DavidsKanal
@DavidsKanal Рік тому
2:15 I'm sorry but I fail to imagine how `random` is declared. I get what you're saying about type inference, but Rust doesn't have function overloading, so we can't define both `fn random() -> u8` and `fn random() -> char`, correct? So, how?
@pehdfms8621
@pehdfms8621 Рік тому
random() -> T
@Betacak3
@Betacak3 Рік тому
The random() function is a generic function that takes a type parameter that extends a trait. Here's how that works: First, you need a trait. Let's call it "Random". It defines a single function that returns the type that implements it: trait Random { fn random() -> Self; } Then, you imlement that trait in another type. impl Random for SomeType { fn random() -> Self { // Return a random instance of SomeType } } Now, the random() function itself will look a little something like this: fn random() -> T { T::random() } So when you call let foo: SomeType = random(), it will internally call the SomeType::random() function. The actual function in the rand crate is actually quite a bit more complicated. But it boils down to this. I hope I managed to explain it well enough.
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you for explaining it, that's very clear!
@flyingsquirrel3271
@flyingsquirrel3271 Рік тому
@@Betacak3 Yes! Rust traits are so versatile, they can even be used like "overloading done right".
@DavidsKanal
@DavidsKanal Рік тому
@@Betacak3 I forgot to thank you for this!
@SriKadimisetty
@SriKadimisetty Рік тому
Nice work, beginning to look forward to these now :) Small feedback though - could you look into putting a pop filter or something similar over your mic, the `s` sounds currently are too harsh on the ears.
@NoBoilerplate
@NoBoilerplate Рік тому
interesting, I'll look into it. (A pop shield won't do anything for sibilants, that's for plosives, but your feedback stands, thank you)
@SriKadimisetty
@SriKadimisetty Рік тому
@@NoBoilerplate Gotcha. I learn something new everyday :)
@NoBoilerplate
@NoBoilerplate Рік тому
@@SriKadimisetty I've got a lifetime of music production under my belt, and 2 years of intensive podcasting for Lost Terminal, so I'm always optimising my audio pipeline! btw have you heard it? ukposts.info/have/v-deo/qGOTeHtwoqmrrpc.html
@eboatwright_
@eboatwright_ Рік тому
These would have been SO HELPFUL for me to learn Rust! Also, I like the little text adventure like style here, because I've been writing a text adventure in Rust (with Macroquad for rendering) for over a year now
@NoBoilerplate
@NoBoilerplate Рік тому
oh sweet!
@Elliot.2591
@Elliot.2591 Рік тому
I noticed you have a lot of unwrap calls. Is it safe to use if you are certain what you are unwrapping will not fail?
@NoBoilerplate
@NoBoilerplate Рік тому
You're quite right, every unwrap call you make is a chance to improve the reliability of your program. However, when you are prototyping, like I am here, you can leave a few in, consider them todos that the compiler understands. I use clippy to warn on them, and turn them into errors in my build pipeline!
@Elliot.2591
@Elliot.2591 Рік тому
@@NoBoilerplate I see. Theres a lot to learn here :)
@eaudesolero5631
@eaudesolero5631 6 місяців тому
Have you given thought to beginning to try to write your own AI/NN/etc using rust?
@NoBoilerplate
@NoBoilerplate 6 місяців тому
It's not in my area of interest, but there's nearly 1000 ML crates already published! lib.rs/science/ml
@ewhac
@ewhac Рік тому
BTW, do you take requests? I've started writing some Rust to fiddle with a USB peripheral, and I've made decent progress with the rusb crate. Where things get messy is interpreting the reports sent by the device. The structure of the USB device's reports are known, and can be represented by a C struct, which we can reproduce in Rust via the #[repr(C)] directive. In C, you would simply setup a byte buffer, have libusb read the report into it, then (essentially) type-cast the buffer contents to the report structure. But typecasting of this type is a big no-no in Rust, especially if the buffer is mutable. There's a facility in the standard library called std::mem::transmute, but it's unsafe, and the autodocs say essentially, "No, seriously, if you think you need this, you probably don't." I took a quick look at serde, but that rabbit hole goes very deep. In short, it looks like all the "obvious" methods for reinterpreting the contents of a memory buffer are unsafe. I was wondering if you knew of a trick that didn't violate Rust's safety rules.
@NoBoilerplate
@NoBoilerplate Рік тому
Did you just "Dude, Seriously?" me and then ask for help 20 minutes later? Don't worry about it, I forgive you, it's UKposts making us talk like this, it's all too confrontational here isn't it! Come chat to me and the smart folks on the discord - I bet there a few people who could help you out! But be sure to be courteous and recognise that you're asking for help, not demanding it.
@ewhac
@ewhac Рік тому
@@NoBoilerplate Your videos are some of the clearest explanations of the advantages and subtleties of Rust I've yet found. It _certainly_ was not my intention to come off as confrontational or entitled, and I apologize.
@NoBoilerplate
@NoBoilerplate Рік тому
@@ewhac Apology absolutely accepted, don't worry about it 🙂
@gkttlr1066
@gkttlr1066 Рік тому
How does Rust type system compares to OCaml's?
@NoBoilerplate
@NoBoilerplate Рік тому
Extremely similar - the original Rust compiler was written in OCaml! I see Rust as Haskell/OCaml dressed in C's clothing (and you can get paid to write it!)
@andreitoterman
@andreitoterman Рік тому
7:01 what about if let Some(ref mut section) = station.sections.iter_mut().find(|m| m.name == section) { section.active = true; }
@NoBoilerplate
@NoBoilerplate Рік тому
Nice, yeah great optimisation!
@dream_emulator
@dream_emulator Рік тому
Awesome possum ⚡️
@NoBoilerplate
@NoBoilerplate Рік тому
Thanks 🤗
@RoamingAdhocrat
@RoamingAdhocrat Рік тому
2:30 can you not create a shuffed vector in one step, by chaining `shuffle` off `collect`?
@NoBoilerplate
@NoBoilerplate Рік тому
Yeah! Well spotted, I love chaining method calls like this!
@RoamingAdhocrat
@RoamingAdhocrat Рік тому
@@NoBoilerplate Then it wouldn't need to be mutable, right? I thought perhaps you'd done it on two lines for readability
@NoBoilerplate
@NoBoilerplate Рік тому
@@RoamingAdhocrat I do try to keep things as readable as I can, and my code is far from perfect! My goal with this video was to talk about structs and enums and emphasise that modelling your correct states is vital when building a Rust app. There are lots of improvements to the code that need doing!
@sharperguy
@sharperguy Рік тому
"Make invalid states unrepresentable" "Don't you see that the whole aim of Newspeak is to narrow the range of thought? In the end we shall make thought-crime literally impossible, because there will be no words in which to express it."
@NoBoilerplate
@NoBoilerplate Рік тому
You've got the principle exactly, nice analogy! I might steal that (with attribution) for a video...! :-D
@sharperguy
@sharperguy Рік тому
@@NoBoilerplate you should credit George Orwell
@NoBoilerplate
@NoBoilerplate Рік тому
@@sharperguy oh yes of course, but I mean the link between limiting invalid states and newspeak - that's great! 🙂
@dominikkormann1840
@dominikkormann1840 Рік тому
in the beginning when implementing the Name enum  5 #[derive(Debug, RandGen, Display)] ■■ this function takes 2 arguments but 1 argument was supplied supplied 1 argument ▎ 4 enum Name { ▎ 3 Akira, Californa, Daedalus, ▎ 2 Eisenberg, Interpid, Miranda, ▎ 1 Nova, Reliant, Sagan ▎ 24 } I get the Error that RandGen takes 2 arguments but 1 is supplied and I cannot get rid of it can someone help?
@dominikkormann1840
@dominikkormann1840 Рік тому
edit: solved. I used the wrong version of rand 0.7 instead of 0.8
@NoBoilerplate
@NoBoilerplate Рік тому
Super! This is somewhat my fault as I don't check in my cargo.toml. I will fix this for the next video!
@CT-cx8yi
@CT-cx8yi Рік тому
What do you use to create your slideshows?
@NoBoilerplate
@NoBoilerplate Рік тому
Obsidian.md. I talked about it in the middle of this video, it's GREAT! ukposts.info/have/v-deo/oZaSgKFsrWmImmQ.html
@CT-cx8yi
@CT-cx8yi Рік тому
Thanks! Great videos.
@NoBoilerplate
@NoBoilerplate Рік тому
@@CT-cx8yi Thank you so much!
@vanvothe4817
@vanvothe4817 Рік тому
I like it
@NoBoilerplate
@NoBoilerplate Рік тому
I love it! horse.gif Have you seen my other videos? don't watch my last one, I made big mistakes about Go lol!
@BranceBoren
@BranceBoren Рік тому
Anyone else read the Rust book in Tris's voice now?
@NoBoilerplate
@NoBoilerplate Рік тому
I sure do
@teeesen
@teeesen Рік тому
Nice video. But here’s what I’m missing: What are the states in the example that are invalid and why are they unrepresentable?
@NoBoilerplate
@NoBoilerplate Рік тому
Ah, it's not the greatest example was it? I have a lot to learn about Rust and I will build better examples as I learn too. HOWEVER the answer here is that the naming examples I used. Strings can have any names, using Enums allows compiler-validated options.
@teeesen
@teeesen Рік тому
Thanks. That’s what I was wondering. It’s a fine example as far as it goes. I can see that Rust enums are an improvement over C enums, but that’s not a high bar. As programmers what we do want to be able to build types that allow objects to reach only valid states. I think the video articulates that goal well. The way to achieve this is some combination of compile time checking and encapsulation. Encapsulation means that the code that needs to be checked to ensure that only valid states can be reached is limited. Obviously strong static type checking helps here. Mutability restrictions also help. In Java, if a field is “final”, I only have to check the code in the constructors to check that its value is legitimate; and if a field is private, I only need to check the code of one class. If a language distinguishes between mutators and accessors, then I don’t need to check the accessors to see that invariants are respected. I don’t know Rust, but maybe it has something to add here. Another thing that helps is if the language gives a way to express invariants in the language itself; Euclid, Turing, and Eiffel all had this combined with runtime checking. Languages like Dafny, with compile-time verification, and languages like Agda, with dependent types (as another commenter mentioned), give you ways to express nontrivial invariants that can be checked at compile time. In a way, this restricts that amount of code that needs to be checked by the developer down to the code that expresses the invariant. It will be interesting to know more about how Rust supports this goal.
@NoBoilerplate
@NoBoilerplate Рік тому
@@teeesen Absolutely, this is a really good idea for a future video - thank you!
@kira.herself
@kira.herself Рік тому
Lovely Name enum :D
@weirdo911aw
@weirdo911aw Рік тому
Mr. Plate, Could you make a video on WebAssembly (please 🥺🥺🥺)? kthanksbye
@NoBoilerplate
@NoBoilerplate Рік тому
I may do in the future, but for now just use yew.rs it's great! And PLEASE! Mr Plate is my father, call me Nob Oiler.
@Speykious
@Speykious Рік тому
"Mr. Plate" lmao
@kungfooman
@kungfooman Рік тому
Does it even support Multiple Dispatch? Everytime I look at Rust, it just looks ugly. Why not something nice like TypeScript, with Rust compiler?
@NoBoilerplate
@NoBoilerplate Рік тому
Can you explain why I would need multiple dispatch? I've not used a language that has it.
@sammcalonan847
@sammcalonan847 Рік тому
What if we played Among Us on the No Boilerplate space station? 😳
@NoBoilerplate
@NoBoilerplate Рік тому
ha!
@tudbut
@tudbut Рік тому
Rust
@NoBoilerplate
@NoBoilerplate Рік тому
Rust
@Dygear
@Dygear Рік тому
Huh, I didn't know that format!("{{self.name}}{{self.age}}") was valid syntax. I gotta go rewrite some of my code.
@NoBoilerplate
@NoBoilerplate Рік тому
It's not - sorry! Typo there. It COMPILES but is not valid!
@Dygear
@Dygear Рік тому
@@NoBoilerplate ha! I was trying to figure out why when I tired it, it didn’t work. This seems like a sensible addition as it does take variable names directly now, why not also structs?
@NoBoilerplate
@NoBoilerplate Рік тому
@@Dygear I had a nightmare I wars writing python and it came true 😂
@MithicSpirit
@MithicSpirit Рік тому
0:36 why would anyone want to program like in OOP? Also Rust does have typeclasses, they're just called traits instead ;)
@NoBoilerplate
@NoBoilerplate Рік тому
Ah yes!
@quettle
@quettle Рік тому
for 7:06, station.sections.iter_mut().find(|m| m.name= = section).expect("...").active = true should work
@NoBoilerplate
@NoBoilerplate Рік тому
.find() - nice!
@RoamingAdhocrat
@RoamingAdhocrat Рік тому
can't put boilers into space. they're too heavy
@hh-dr4db
@hh-dr4db Рік тому
What is that noise?
@NoBoilerplate
@NoBoilerplate Рік тому
You'll have to be more specific!
@PokeNebula
@PokeNebula Рік тому
i enjoy your other videos, as theyre what motivated me to learn rust to supplement my own diet of python spaghetti, but after a point the insights of a long-time developer would do nothing but go over the head of a beginner like me. Thats why this video made me so excited, before i wasted a lot of time over this confusion: at 1:12 you introduce the rand_derive 2 crate and the randgen trait, but not Display. Is this a mistake? i had to go looking through the docs.rs to find the displaydoc crate, and i still couldnt be sure it was the right crate with a Display trait, since you don't show the use statement that would clarify. even then, the text you show on screen wouldnt compile: the Display trait asks you to write doc comments for every member of the enum...... which is redundant, because the enum's members are names, and names are self-explanatory. You never mention the Display trait by name in the video, and using the displaydoc crate, the code on screen woud not compile, and if it did, then the trait would seemingly help nothing. Is its inclusion in error?
@NoBoilerplate
@NoBoilerplate Рік тому
Take a look at the source markdown, on my linked repo, some code I have no time to show in the videos, but the compiler sees it! I should have included a note about Display, however. Thank you!
@notusingmyrealnamegoogle6232
@notusingmyrealnamegoogle6232 Рік тому
While I think we all appreciate the hustle of trying to get more views for your projects the length of the pitch for the podcasts is beginning to distract from the content of these videos which are where you are excelling and finding an audience.
@NoBoilerplate
@NoBoilerplate Рік тому
I understand, it won't be an often repeated thing. However your options are for me to tell you about my own projects for 30s or to advertise NordVPN for 30s. I am not very interested in nordvpn.
@Yotanido
@Yotanido Рік тому
@@NoBoilerplate Honestly, I think it was fine. I sponsor block, but have it set to not automatically skip self-promotions. It gave me the option, but I decided not to skip it. It's not like some other videos where they have 3 minute sponsor segments in their 5 minute videos... Plus, it was at least tangentially relevant to the video, so it wasn't as jarring as these things usually are.
@notusingmyrealnamegoogle6232
@notusingmyrealnamegoogle6232 Рік тому
@@NoBoilerplate yeah that’s fair, the deeper integration into the video in this case threw me off because it wasn’t clear how much of the topic was guided by what you think is most useful to know and what was relevant to podcasts
@NoBoilerplate
@NoBoilerplate Рік тому
@@notusingmyrealnamegoogle6232 Thank you for your understanding. I will very likely do a few external sponsors now and then, but not freakin' squarespace, I'd rather they be Rust specific companies or tech or something relevant to my audience. The bottom line is that if I can make some money from these videos I can do fewer hours at my day job and make more and better videos for the channel!
@AshtonSnapp
@AshtonSnapp Рік тому
And of course, I’m going to take this and blow the scope like a hot air balloon.
@NoBoilerplate
@NoBoilerplate Рік тому
BUILD IT!
@heraclitoqsaldanha6133
@heraclitoqsaldanha6133 Рік тому
🦀
@NoBoilerplate
@NoBoilerplate Рік тому
ferris!
@SeniorSpaceflight
@SeniorSpaceflight Рік тому
am am i the only one who thought he was gonna make a space station in Rust THE SURVIVAL GAME RUST?
@NoBoilerplate
@NoBoilerplate Рік тому
ikr
@ewhac
@ewhac Рік тому
0:30: "But how do we design programs in Rust? There's no classes!" Dude, seriously? Some of your audience are veteran users of C and assembly code, and they don't have classes, either. 6:00: _(sigh...)_ I've never understood this pattern -- two different functions that, save for one tiny difference, perform _identical_ operations. This way leads to code bloat. You should parameterize the boolean test, along the lines of (horrible formatting ahead): fn sections_with_active (&self, active: bool) -> Vec { self.sections.iter().filter (|m| m.active == active).map (|m| m.name.to_string()).collect() } Which you can then call as `station.sections_with_active (true)` or `station.sections_with_active (false)`, which is hopefully sufficiently mnemonic.
@NoBoilerplate
@NoBoilerplate Рік тому
noted.
@31redorange08
@31redorange08 Рік тому
Boolean parameters considered harmful.
@Jakob7539511
@Jakob7539511 Рік тому
@@31redorange08 That's mainly for flags, that change the control flow of the whole method. This use looks very nice :)
@Yotanido
@Yotanido Рік тому
I don't really like that as a public API. It doesn't read as nice. You could absolutely have working_sections and broken_sections call this new sections_with_active, though - I do prefer that.
@Mankepanke
@Mankepanke Рік тому
F in the chat for all the dogs killed by people reading their name tags. Dead, but not forgotten 🕊️🕊️🕊️
@NoBoilerplate
@NoBoilerplate Рік тому
I don't understand?
@Mankepanke
@Mankepanke Рік тому
@@NoBoilerplate The name tag method used "self" and not "&self", so the method took ownership of the dog and freed it. Try it yourself, you cannot access the dog instance after calling the name tag method. It's just a joke, though. :)
@NoBoilerplate
@NoBoilerplate Рік тому
@@Mankepanke oh so it did! Ha!
@ameypendokhare3832
@ameypendokhare3832 Рік тому
NASA should use rust as their official programming language... (after watching this I hope so) its always better to evolve with time RUST is evolution... >Rust for next 40 years {spread the word}
@NoBoilerplate
@NoBoilerplate Рік тому
Rust's not yet PROVEN (mathematically) for safety critical systems, when people's lives are on the line, you gotta be SURE. It may be, but it's not there yet. Doesn't matter for 99.99% of applications, of course. (how else do you explain php?!)
@lucky-segfault4219
@lucky-segfault4219 Рік тому
@@NoBoilerplate are there any languages that are proven mathematically? surely C can't be with all the many many many ways there are to trigger undefined behavior
@NoBoilerplate
@NoBoilerplate Рік тому
@@lucky-segfault4219 The ones used in autopilots and pacemakers are, en.wikipedia.org/wiki/Ada_(programming_language) and co. They either use or have core features proven by Formal Methods such as Z, B, Coq and so on. It's not really a deficiency in Rust, as to formally prove programs, their state has to be SO TINY (think pacemaker inputs and outputs) and a single unbounded string can make your function impossible to prove.
@lucky-segfault4219
@lucky-segfault4219 Рік тому
@@NoBoilerplate oh neat. Well, it sounds like rusts ability to create programs that can't represent invalid states might be a useful base for proving individual programs are mathematically provable, even if the language itself still has openings for errors
@NoBoilerplate
@NoBoilerplate Рік тому
@@lucky-segfault4219 Certainly. Just like seatbelts, a policy doesn't have to stop every fatality for it to be wildly successful. Rust feels like 99% of my day-to-day errors in python just can't happen. Wonderful!
@oconnor663
@oconnor663 Рік тому
> I'm not delighted by having to resort to indexing the vector. I would lean towards using a regular for-loop for this, maybe something like: for section in &mut station.sections { if section.name == section_name { section.active = true; // break? } } You could also consider making your sections a HashMap instead of a Vec, with the section name enum as the key to the map. That would let you get rid of the loop here, and it would let you guarantee that you never have multiple sections with the same name. If you wanted to get really crazy, you could even assign values starting with 0 to your SectionName enum, and you could use an array of (optional?) Sections indexed by the value of their SectionName. Ideally you could set the size of the array to the number of enum variants without any duplication, but I'm not sure there's a good way to do that today. Something more verbose like this example using a struct could also work: doc.rust-lang.org/std/ops/trait.Index.html#examples
@NoBoilerplate
@NoBoilerplate Рік тому
Nice! I've also had suggestions of using inter.find().
@ironnoriboi
@ironnoriboi Рік тому
To think that I'd need Sponsorblocker for your videos. Bleh
@NoBoilerplate
@NoBoilerplate Рік тому
I don't mind at all, I totally understand. However, I'm hoping to do these videos professionally, and the way to do that is through advertising. If I can get sponsorship from relevant companies (not squarespace lol) then I'll be able to dedicate more time to making these videos for you. That sounds like a win/win for everyone!
@ironnoriboi
@ironnoriboi Рік тому
@@NoBoilerplate I'm of the opinion that people UKposts-ing fulltime ruined the feeling of the platform. It is very corporate and business now. It is hard to find users that make videos in their free time for fun, which was very easy years ago when UKposts was still a smaller platform where nearly nobody did it full time.
@NoBoilerplate
@NoBoilerplate Рік тому
@@ironnoriboi I don't think this is the right way to look at it. Let me know your thoughts on this, which says it much better than I could: ukposts.info/have/v-deo/q4WkfWyObmOVk2w.html
@lucky-segfault4219
@lucky-segfault4219 Рік тому
7:01 I'd use the filter Function. For example, you can remove all elements of a list that are 3 like this: let v = vec![ 1, 3, 2, 11, u16::MAX ]; let v = v.into_iter() .filter( | item | item != 3 ) .collect(); Great video, and I'll be sure to have a look at that podcast
@NoBoilerplate
@NoBoilerplate Рік тому
nice thank you! I do hope you like the podcast, it's something I'm so proud of!
@sodiboo
@sodiboo Рік тому
7:00 how about this? station.sections .iter_mut() .find(|m| m.name) .expect("Section not found.") .active = true;
@NoBoilerplate
@NoBoilerplate Рік тому
perfect!
@urbanelemental3308
@urbanelemental3308 Рік тому
@NoBoilerplate, here's what ChatGPT helped me make. Is there no crate already out there that does this? use std::io::{stdout, stdin, Write}; use std::str::FromStr; pub fn prompt(message: &str, validate: F) -> T where T: FromStr, T::Err: std::fmt::Debug, F: Fn(&str) -> Result { loop { print!("{}", message); stdout().flush() .expect("Failed to flush stdout"); let mut input = String::new(); stdin().read_line(&mut input) .expect("Failed to read input"); let input = input.trim(); match validate(input) { Ok(value) => return value, Err(error) => println!("{}", error), } } } pub fn prompt_value(message: &str) -> T where T: FromStr, T::Err: std::fmt::Debug { prompt(message, |input| { match input.parse() { Ok(value) => Ok(value), Err(_) => Err("Error parsing input"), } }) }
@NoBoilerplate
@NoBoilerplate Рік тому
ChatGPT's fun isn't it! I also am using as part of my daily work. HOWEVER this seems wildly complex. Do you really need all that generic stuff? I see you're more interested in the input side than the validate side (your code expects a validate function to be passed in) There's lots of input crates available crates.io/search?q=input What are you attempting to do?
@urbanelemental3308
@urbanelemental3308 Рік тому
@@NoBoilerplate With the FromStr (trait?) it allows for identifying a parsable type. That way you can simply do this: mod prompt; use prompt::prompt_value; fn main() { let age = prompt_value::("Enter your age: "); println!("Your age is: {}", age); } It's nice because prompt_value won't return until it has a valid value. Command line apps are my way of experimenting.
@NoBoilerplate
@NoBoilerplate Рік тому
@@urbanelemental3308 that's so cool! Turbofish is a DELIGHT
@urbanelemental3308
@urbanelemental3308 Рік тому
@@NoBoilerplate Ah yes. I love that iterables are seemly built in.
@NoBoilerplate
@NoBoilerplate Рік тому
@@urbanelemental3308 oh I LOVE iters. Have you seen: crates.io/crates/rayon
@YTCrazytieguy
@YTCrazytieguy Рік тому
I think you want: station.sections.iter_mut().find(|m| m.name == section).expect("Section not found.").active = true;
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you!
@real1cytv
@real1cytv Рік тому
7:05 what about the Iterator::find method? You can just use a |m| m.name == section as the predicate...
@NoBoilerplate
@NoBoilerplate Рік тому
nice!
@robinmoussu
@robinmoussu Рік тому
You have an interesting channel. I just discovered it thanks to @codetothemoon
@NoBoilerplate
@NoBoilerplate Рік тому
Thank you so much! My latest video has a shout-out to CTTM :-)
@localboxcrox
@localboxcrox Рік тому
🦀
@NoBoilerplate
@NoBoilerplate Рік тому
Ferris!
Rust on Rails
11:34
No Boilerplate
Переглядів 128 тис.
The Unreasonable Effectiveness Of Plain Text
14:37
No Boilerplate
Переглядів 567 тис.
Rust Data Modelling Without Classes
11:25
No Boilerplate
Переглядів 156 тис.
rust runs on EVERYTHING (no operating system, just Rust)
18:10
Low Level Learning
Переглядів 334 тис.
Projects Every Programmer Should Try
16:58
ThePrimeTime
Переглядів 328 тис.
Hack Your Brain with Polyphasic Sleep
11:02
No Boilerplate
Переглядів 1,2 млн
ADHD: A Left-handed Brain
19:36
No Boilerplate
Переглядів 106 тис.
Rust Modules - Explained Like I'm 5
19:59
Let's Get Rusty
Переглядів 66 тис.
Rust makes you feel like a GENIUS
10:48
No Boilerplate
Переглядів 396 тис.
Rust is not a faster horse
11:37
No Boilerplate
Переглядів 314 тис.
A Simpler Way to See Results
19:17
Logan Smith
Переглядів 91 тис.