Building a space station in Rust

Поделиться
HTML-код
  • Опубликовано: 24 ноя 2024

Комментарии • 278

  • @NoBoilerplate
    @NoBoilerplate  2 года назад +136

    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 2 года назад +10

      dont forget to pin this comment ;)

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +17

      @@KyraKrassenburg omgggggg youtube LOVES unpinning it when I edit - THANK YOU!

    • @KyraKrassenburg
      @KyraKrassenburg 2 года назад +9

      @@NoBoilerplate haha i didnt realise thats what happened.. thats odd lol

    • @xanri7673
      @xanri7673 2 года назад +4

      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 2 года назад +5

      It was removed from pin once again.

  • @zyansheep
    @zyansheep 2 года назад +141

    Hey look ma, No Boilerplate uploaded again!

  • @tylerbloom4830
    @tylerbloom4830 2 года назад +143

    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  2 года назад +33

      now that is COOL!

    • @ArrekinWorks
      @ArrekinWorks 2 года назад +5

      Could you post a small working example?

    • @tylerbloom4830
      @tylerbloom4830 2 года назад +18

      ​@@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: RUclips doesn't like me posting links, so go to the Rust playground and add gist=34f765f98445ca4c2e8da6fbab6a53f8 to the URL​

    • @ArrekinWorks
      @ArrekinWorks 2 года назад +2

      @@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 2 года назад +2

      @@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.

  •  2 года назад +148

    From "you can use rust to make your life simpler" to "LETS BUILD A SPACE STATION"
    I like where this is going!

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +25

      TO THE MOON!

    • @w1keee
      @w1keee 2 года назад +16

      @@NoBoilerplate come to think of it, rust would be perfect for infrastructure on the moon!

    • @notdumbrella6399
      @notdumbrella6399 Год назад

      @@w1keee And the Mars

  • @w1keee
    @w1keee 2 года назад +88

    the unrepresantability of invalid states is one of my favourite rust features. i hope the devs add ranged integers soon!

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +22

      There's already crates that do this, get to it!

    • @Rudxain
      @Rudxain 2 года назад +1

      Exactly what I was thinking!

    • @r.pizzamonkey7379
      @r.pizzamonkey7379 Год назад +3

      @@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.

  • @clayhudson8892
    @clayhudson8892 2 года назад +10

    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  2 года назад +3

      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 ruclips.net/video/p3bDE9kszMc/видео.html

    • @erikyoung5139
      @erikyoung5139 Год назад +1

      @@NoBoilerplate I use it for this precise purpose.

    • @NoBoilerplate
      @NoBoilerplate  Год назад

      @@erikyoung5139 thank you!

  • @Singhrager
    @Singhrager 2 года назад +27

    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  2 года назад +4

      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 2 года назад +3

      @@NoBoilerplate Desktop apps with Tauri, crypto with Solana..

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +1

      @@lardosian Tauri isn't really Rust, I'd spend my days writing my javascript app INSIDE Tauri, right?

    • @lardosian
      @lardosian 2 года назад +2

      @@NoBoilerplate Have not actually used Tauri, just heard about it recently.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +2

      @@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...!

  • @martinbecker1069
    @martinbecker1069 2 года назад +10

    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.

  • @daskadse769
    @daskadse769 2 года назад +33

    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  2 года назад +9

      Thank you!

    • @Betacak3
      @Betacak3 2 года назад +10

      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  2 года назад +1

      @@Betacak3 Nice, that's much better than indexing!

  • @ottergauze
    @ottergauze 2 года назад +3

    I just came across this channel and, wow, it has completely revitalised my drive to make stuff in Rust.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      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)

  • @rotteegher39
    @rotteegher39 Год назад +2

    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 :-)

  • @feathecutie9942
    @feathecutie9942 2 года назад +7

    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  2 года назад

      I'm so pleased! Thank you! LT is my favourite thing in the WORLD!

  • @messester7675
    @messester7675 2 года назад +3

    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  2 года назад +2

      Well thank you so much! I plan to write a video on Rust modules in a similar way soon!

  • @ShreksSpliff
    @ShreksSpliff 2 года назад +5

    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  2 года назад

      Thanks for the tips Wayne, always appreciated. Could you give me specific timecodes for the problems you're mentioning? Thank you!

    • @BenjaminBrienen
      @BenjaminBrienen 2 года назад +1

      @@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 2 года назад +2

      @@NoBoilerplate The voice and cadence is literally a + in my opinion.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      @@dardevelin Thank you so much! I just wrapped season 9 of Lost Terminal - I've had a LOT of practice! ruclips.net/video/p3bDE9kszMc/видео.html

  • @aidensandbakken6648
    @aidensandbakken6648 2 года назад +5

    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  2 года назад +3

      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! ;-)

  • @Yotanido
    @Yotanido 2 года назад +7

    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  2 года назад +1

      thank you so much for telling me this, I now have a name for the pattern!

    • @darrennew8211
      @darrennew8211 2 года назад

      @@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.

  • @dedenapraia
    @dedenapraia Год назад +2

    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! ruclips.net/video/Q3AhzHq8ogs/видео.html

  • @fallout__boy1130
    @fallout__boy1130 2 года назад +1

    Just discover this channel yesterday. This is really nice content, your voice is pleasing to listen to!

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      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! ruclips.net/video/p3bDE9kszMc/видео.html

  • @Ehomer0815
    @Ehomer0815 2 года назад +2

    New rust video from tris.. instant like

  • @pup4301
    @pup4301 2 года назад +2

    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  2 года назад +1

      oh cool, I'll look that up, thank you!

    • @pup4301
      @pup4301 2 года назад +1

      Welcome.

  • @tentaklaus9382
    @tentaklaus9382 2 года назад +5

    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  2 года назад +4

      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.

  • @eignnx_1738
    @eignnx_1738 2 года назад +1

    I love the crate suggestions! There are so many great crates out there I didn't even know I wanted

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      I've not even SCRATCHED the surface! look at THIS crates.io/crates/no-panic

  • @seubmarine5347
    @seubmarine5347 2 года назад +7

    Wake up babe.
    New No Boilerplate video just dropped.

  • @deer6413
    @deer6413 Год назад +1

    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  Год назад +1

      Try out crates.io/crates/bracket-terminal for your simple game engine!

  • @Medik_0001
    @Medik_0001 2 года назад +1

    Love Cool Retro Term. I've also used it for videos myself, love to see it used here also!

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +1

      Thank you so much! Did you see the podcast videos? ruclips.net/video/p3bDE9kszMc/видео.html

  • @costelinha1867
    @costelinha1867 2 года назад +15

    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...)

  • @SEOTADEO
    @SEOTADEO 2 года назад +1

    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  2 года назад

      Thank you so much! If you'd like to listen more, you might like my scifi podcast Lost Terminal ruclips.net/video/p3bDE9kszMc/видео.html

    • @SEOTADEO
      @SEOTADEO 2 года назад +1

      @@NoBoilerplate Thanks for the hint! I'll listen to everything :)

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      @@SEOTADEO Do comment as you go, I'd love to know your thoughts!

  • @the_kovic
    @the_kovic 2 года назад +1

    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  2 года назад +2

      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.

  • @doormango
    @doormango 2 года назад +5

    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  2 года назад

      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 2 года назад +1

      ​@@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  2 года назад

      @@doormango I'll have to trust you on that.

  • @joserobjr7010
    @joserobjr7010 2 года назад +6

    Simply amazing!

  • @eboatwright_
    @eboatwright_ 2 года назад +3

    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

  • @skylark.kraken
    @skylark.kraken 2 года назад +5

    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  2 года назад +3

      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 2 года назад +9

      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 2 года назад +4

      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.

  • @barisbayrak
    @barisbayrak 2 года назад +1

    Amazing content. Glad you exist.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      What a nice thing to say! You're very kind, thank you!

  • @FelipeBalbi
    @FelipeBalbi 2 года назад +1

    This was a very entertaining video 🙂 Thoroughly enjoyed

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      Thank you so much! There's 12 others in my rust series, I'd love to know what you think about the others!

  • @ДаниилРабинович-б9п
    @ДаниилРабинович-б9п 2 года назад +4

    7:00 I think you could use
    *station.section.iter_mut()
    .find(...)
    .expect(...)
    .active = true;
    or something like that.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      .find()! nice!

    • @Tigregalis
      @Tigregalis 2 года назад +1

      @@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  2 года назад

      @@Tigregalis no clippy help this time for me, I always run it! thank you!

  • @gold15o2
    @gold15o2 Год назад +2

    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  Год назад +1

      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

  • @bmanturner
    @bmanturner 2 года назад +1

    Instant subscribe. Great video. Informative, interesting and moderately brief

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      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 2 года назад +1

      @@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  2 года назад

      @@bmanturner Thank you so much! 9 seasons so far!

  • @creeperkafasi
    @creeperkafasi 2 года назад +2

    Thanks for another great video!

  • @Rudxain
    @Rudxain 2 года назад +5

    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 2 года назад +2

      couldnt this be done manually by writing another line of code with the assert macros?

    • @blucky_yt
      @blucky_yt 2 года назад +2

      @@PokeNebula Assertion happens at runtime iirc, but you're on the right track, this could probably be implemented with macros

    • @sodiboo
      @sodiboo 2 года назад +4

      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 2 года назад +1

      @@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 2 года назад +2

      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.

  • @notusingmyrealnamegoogle6232
    @notusingmyrealnamegoogle6232 2 года назад +3

    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  2 года назад +4

      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 2 года назад +2

      @@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 2 года назад +1

      @@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  2 года назад +1

      @@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!

  • @Elliot.2591
    @Elliot.2591 2 года назад +2

    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  2 года назад +1

      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 2 года назад

      @@NoBoilerplate I see. Theres a lot to learn here :)

  • @SriKadimisetty
    @SriKadimisetty 2 года назад +2

    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  2 года назад +3

      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 2 года назад +1

      @@NoBoilerplate Gotcha. I learn something new everyday :)

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +3

      @@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? ruclips.net/video/p3bDE9kszMc/видео.html

  • @DavidsKanal
    @DavidsKanal 2 года назад +4

    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 2 года назад

      random() -> T

    • @Betacak3
      @Betacak3 2 года назад +13

      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  2 года назад +1

      Thank you for explaining it, that's very clear!

    • @flyingsquirrel3271
      @flyingsquirrel3271 2 года назад

      @@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!

  • @AceofSpades5757
    @AceofSpades5757 2 года назад +1

    Fun and informative. Thanks!

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      Thank you so much! Did you see my other videos in this Rust series?

    • @AceofSpades5757
      @AceofSpades5757 2 года назад +1

      @@NoBoilerplate Yup, looks like almost all of them. I'll probably be checking out the couple I missed this afternoon.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      @@AceofSpades5757 How super, I'd love to hear what you think of them, if you fancy commenting on them.

  • @nellykantu8428
    @nellykantu8428 2 года назад +1

    You're amazing fr, wish i could code like u

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +1

      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 2 года назад +2

      @@NoBoilerplate I'm still beginner, was learning Java but dropped it to learn rust

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      @@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 2 года назад +1

    You absolute legend

  • @ewhac
    @ewhac 2 года назад +3

    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  2 года назад +5

      Did you just "Dude, Seriously?" me and then ask for help 20 minutes later?
      Don't worry about it, I forgive you, it's RUclips 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 2 года назад +3

      @@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  2 года назад

      @@ewhac Apology absolutely accepted, don't worry about it 🙂

  • @teeesen
    @teeesen 2 года назад +1

    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  2 года назад +1

      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 2 года назад +2

      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  2 года назад

      @@teeesen Absolutely, this is a really good idea for a future video - thank you!

  • @lucky-segfault
    @lucky-segfault 2 года назад +3

    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  2 года назад +1

      nice thank you! I do hope you like the podcast, it's something I'm so proud of!

  • @ayoubboudouh7440
    @ayoubboudouh7440 2 года назад

    You do great work bro. Keep it up bro.❤❤

  • @sharperguy
    @sharperguy Год назад +1

    "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 Год назад +1

      @@NoBoilerplate you should credit George Orwell

    • @NoBoilerplate
      @NoBoilerplate  Год назад +1

      @@sharperguy oh yes of course, but I mean the link between limiting invalid states and newspeak - that's great! 🙂

  • @eaudesolero5631
    @eaudesolero5631 Год назад +1

    Have you given thought to beginning to try to write your own AI/NN/etc using rust?

    • @NoBoilerplate
      @NoBoilerplate  Год назад

      It's not in my area of interest, but there's nearly 1000 ML crates already published! lib.rs/science/ml

  • @tgirlshark
    @tgirlshark 2 года назад +1

    Lovely Name enum :D

  • @plato4ek
    @plato4ek 2 года назад +2

    Hi! What is that `literate` program used to extract the source code in rust, and where can I find it?

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +1

      well spotted! It's a crate, just install it with `cargo install literate`!
      I'll update the readme

  • @BranceBoren
    @BranceBoren 2 года назад +1

    Anyone else read the Rust book in Tris's voice now?

  • @Dygear
    @Dygear 2 года назад +1

    Huh, I didn't know that format!("{{self.name}}{{self.age}}") was valid syntax. I gotta go rewrite some of my code.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +1

      It's not - sorry! Typo there. It COMPILES but is not valid!

    • @Dygear
      @Dygear 2 года назад +1

      @@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  2 года назад

      @@Dygear I had a nightmare I wars writing python and it came true 😂

  • @dream_emulator
    @dream_emulator 2 года назад

    Awesome possum ⚡️

  • @devchaudhary78
    @devchaudhary78 2 года назад

    Nyc video, something unique thanks man❤️🙂

  • @RoamingAdhocrat
    @RoamingAdhocrat 2 года назад +1

    2:30 can you not create a shuffed vector in one step, by chaining `shuffle` off `collect`?

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      Yeah! Well spotted, I love chaining method calls like this!

    • @RoamingAdhocrat
      @RoamingAdhocrat 2 года назад +1

      @@NoBoilerplate Then it wouldn't need to be mutable, right? I thought perhaps you'd done it on two lines for readability

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      @@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!

  • @gkttlr1066
    @gkttlr1066 2 года назад +1

    How does Rust type system compares to OCaml's?

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +1

      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!)

  • @hussein7859
    @hussein7859 2 года назад +1

    this is amazing!

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +1

      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 2 года назад +1

      @@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  2 года назад +1

      @@hussein7859 I'm so pleased! Do come and chat on my discord, ask any questions in #newbie-advice if you need!

    • @hussein7859
      @hussein7859 2 года назад +1

      @@NoBoilerplate I will, Thanks!

  • @vanvothe4817
    @vanvothe4817 2 года назад +1

    I like it

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      I love it! horse.gif
      Have you seen my other videos? don't watch my last one, I made big mistakes about Go lol!

  • @CT-cx8yi
    @CT-cx8yi 2 года назад +1

    What do you use to create your slideshows?

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +1

      Obsidian.md. I talked about it in the middle of this video, it's GREAT! ruclips.net/video/ifaLk5v3W90/видео.html

    • @CT-cx8yi
      @CT-cx8yi 2 года назад +1

      Thanks! Great videos.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      @@CT-cx8yi Thank you so much!

  • @quettle
    @quettle 2 года назад +1

    for 7:06, station.sections.iter_mut().find(|m| m.name= = section).expect("...").active = true should work

  • @weirdo911aw
    @weirdo911aw 2 года назад +4

    Mr. Plate,
    Could you make a video on WebAssembly (please 🥺🥺🥺)?
    kthanksbye

    • @NoBoilerplate
      @NoBoilerplate  2 года назад +2

      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 2 года назад +1

      "Mr. Plate"
      lmao

  • @tudbut
    @tudbut 2 года назад +3

    Rust

  • @andreitoterman
    @andreitoterman 2 года назад +2

    7:01 what about
    if let Some(ref mut section) = station.sections.iter_mut().find(|m| m.name == section) {
    section.active = true;
    }

  • @sammcalonan847
    @sammcalonan847 2 года назад +2

    What if we played Among Us on the No Boilerplate space station? 😳

  • @AshtonSnapp
    @AshtonSnapp 2 года назад +1

    And of course, I’m going to take this and blow the scope like a hot air balloon.

  • @MithicSpirit
    @MithicSpirit 2 года назад +1

    0:36 why would anyone want to program like in OOP? Also Rust does have typeclasses, they're just called traits instead ;)

  • @dominikkormann1840
    @dominikkormann1840 2 года назад +1

    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 2 года назад +1

      edit: solved. I used the wrong version of rand 0.7 instead of 0.8

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      Super! This is somewhat my fault as I don't check in my cargo.toml. I will fix this for the next video!

  • @RoamingAdhocrat
    @RoamingAdhocrat 2 года назад +1

    can't put boilers into space.
    they're too heavy

  • @kungfooman
    @kungfooman 2 года назад +1

    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  2 года назад

      Can you explain why I would need multiple dispatch? I've not used a language that has it.

  • @ManimsohungryIcouldeata
    @ManimsohungryIcouldeata 2 года назад +1

    am
    am i the only one who thought he was gonna make a space station in Rust
    THE SURVIVAL GAME RUST?

  • @PokeNebula
    @PokeNebula 2 года назад +1

    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  2 года назад

      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!

  • @hh-dr4db
    @hh-dr4db 2 года назад +1

    What is that noise?

  • @localboxcrox
    @localboxcrox 2 года назад +1

    🦀

  • @oconnor663
    @oconnor663 2 года назад +1

    > 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  2 года назад

      Nice! I've also had suggestions of using inter.find().

  • @Mankepanke
    @Mankepanke 2 года назад

    F in the chat for all the dogs killed by people reading their name tags.
    Dead, but not forgotten 🕊️🕊️🕊️

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      I don't understand?

    • @Mankepanke
      @Mankepanke 2 года назад +1

      @@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  2 года назад +1

      @@Mankepanke oh so it did! Ha!

  • @ewhac
    @ewhac 2 года назад +2

    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  2 года назад +1

      noted.

    • @31redorange08
      @31redorange08 2 года назад +1

      Boolean parameters considered harmful.

    • @Jakob7539511
      @Jakob7539511 2 года назад +1

      @@31redorange08 That's mainly for flags, that change the control flow of the whole method. This use looks very nice :)

    • @Yotanido
      @Yotanido 2 года назад +3

      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.

  • @ameypendokhare3832
    @ameypendokhare3832 2 года назад +2

    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  2 года назад +2

      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-segfault
      @lucky-segfault 2 года назад +1

      @@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  2 года назад

      @@lucky-segfault 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-segfault
      @lucky-segfault 2 года назад +1

      @@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  2 года назад

      @@lucky-segfault 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!

  • @ironnoriboi
    @ironnoriboi 2 года назад

    To think that I'd need Sponsorblocker for your videos. Bleh

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      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 2 года назад +1

      @@NoBoilerplate I'm of the opinion that people RUclips-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 RUclips was still a smaller platform where nearly nobody did it full time.

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      @@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: ruclips.net/video/sUsI6W7-d28/видео.html

  • @urbanelemental3308
    @urbanelemental3308 Год назад +1

    @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 Год назад +1

      @@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 Год назад +1

      @@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

  • @sodiboo
    @sodiboo 2 года назад +2

    7:00 how about this?
    station.sections
    .iter_mut()
    .find(|m| m.name)
    .expect("Section not found.")
    .active = true;

  • @YTCrazytieguy
    @YTCrazytieguy 2 года назад +1

    I think you want:
    station.sections.iter_mut().find(|m| m.name == section).expect("Section not found.").active = true;

  • @real1cytv
    @real1cytv 2 года назад +1

    7:05 what about the Iterator::find method? You can just use a |m| m.name == section as the predicate...

  • @robinmoussu
    @robinmoussu 2 года назад +1

    You have an interesting channel. I just discovered it thanks to @codetothemoon

    • @NoBoilerplate
      @NoBoilerplate  2 года назад

      Thank you so much! My latest video has a shout-out to CTTM :-)

  • @heraclitoqsaldanha6133
    @heraclitoqsaldanha6133 2 года назад +1

    🦀