Тёмный
Fio's Quest
Fio's Quest
Fio's Quest
Подписаться
Learning to code can be hard, but you can do it if its what you want to do!

Fio believes in you and so do I.
Комментарии
@Winnetou17
@Winnetou17 18 дней назад
So stop using mocks directly and mock behind an interface, got it!
@selvamp5775
@selvamp5775 22 дня назад
Nice, have a question. You mentioned there is less job, where(domain, use cases) it gain popularity in future?
@FiosQuest
@FiosQuest 22 дня назад
Thanks! (TLDR at the bottom) It's true that there aren't many Rust jobs right now though adoption this year seems to have picked up quite a bit so fingers crossed this is going to change. @letsgetrusty recently did a great video on growth areas: "Where is Rust being used?" which covers some of this. I generally think that companies who build tools for speed and safety should be taking a serious look at Rust right now, particularly things like; vehicle control software, robotics, automation, or any software that causes something to physically move should seriously consider moving to Rust as soon as possible because the tooling makes it much easier to write code confidently than older languages like C or C++. Indeed, that is what we’re seeing happen. But actually, there’s few industries that wouldn’t benefit from making the switch. Personally I’m from the web tech space and I used to argue against swapping to Rust (as much as I love it) because speed isn’t everything, what does it matter if Rust can get you an API response in 2ms if TypeScript can do it in 8ms, and that’s the technology most web developers are using? However, I’ve actually started to change my mind on this. The internet uses 4-6% of global energy (in 2020, mid pandemic so take it with a pinch of salt), more than the entire aviation industry. If everyone started writing APIs that were 4x faster, this would have a significant impact on the environment. But, environmentalism is a poor motivator, so it’s a difficult argument to make, particularly in smaller companies who aren’t worried about the cost of scale. TL;DR: I’m not sure where I see being the biggest growth area for getting a job in Rust in the near future, which is why I can’t recommend learning Rust to get a job right now. In my opinion, it’s better to find an industry that interests you, learn the most common tools for that industry and, once you’re in a position of influence, and can objectively identify problems that can be best solved with Rust, to make that call yourself. To get there though requires understanding the industry and the people within it which is why I often say, the role of a software engineer is not to write code but to solve problems, the technology (even if its Rust) doesn’t actually matter.
@selvamp5775
@selvamp5775 22 дня назад
Thanks for the kind reply.
@selvamp5775
@selvamp5775 22 дня назад
Go is good for backend development? Or Node/TS?
@FiosQuest
@FiosQuest 22 дня назад
@@selvamp5775 It perhaps depends on the specific kind of Backend dev. If you want to do what I might call "normal backend webdev" then there's no question JS/TS dominate. If you're looking at lower level things to do with network communication (the sort of things Cloudflare, Netlify, et al do) then the library ecosystem in Go is much richer so a lot of those companies use that. I'd describe myself as a fullstack web developer, and TypeScript(/JS/Flow) has been my go to for ~7 years. The big benefit for me is isomorphism which Go and Rust aren't _quite_ there with yet (though Rust is really, really close with things like Dioxus which is what the Fios Quest website was made with).
@misterwoody_
@misterwoody_ Месяц назад
Is the idiomatic rust name for a "static type" an "associated type"? (e.g. the new function). And also a getter is called a method?
@FiosQuest
@FiosQuest Месяц назад
Hi there! I'm not sure what a "static type" would be normally. "Static typing" in languages is when a language won't allow you to change the type of a variable. Eg, statically typed languages, which Rust is, don't allow you to do something like: let a = 10; a = "bob"; // this won't work as a is a number There are many statically typed languages that do this including; C, C++, Java, Go, and more! Static values are achievable in Rust as well using the "const" keyword which I haven't gone over yet. There is also the concept of static lifetimes (&'static) in Rust which are given to any value that is guaranteed to always be accessible because it was built in at compile time, eg: let a = "hello"; This technically has a static lifetime as the value "hello" will be part of the compiled binary and therefore always exist while the program is running. Static methods are also something in Rust which are functions that are attached to Types, such as "new" or other constructors which are not part of the instantiated value. Rust has a concept of Associated Types which are a more advanced topic where Traits can specify a type that is actually chosen when the trait is implemented. An example of this is the Iterator trait which has an associated Item type that you must explicitly decide on when implementing Iterator. See: doc.rust-lang.org/std/iter/trait.Iterator.html Getters are a subset of methods. Methods are functions that will work on an instantiated type (a value of a given type) and will allow you to "get" data from inside of the constructed value, usually something that might otherwise be private. This is really helpful to restrict _how_ data can be accessed and manipulated. I appreciate this is a fairly light touch explanation, I hope it helps. LMK if I can clarify anything further.
@misterwoody_
@misterwoody_ Месяц назад
@@FiosQuest Ah apologies - I meant "Static method" - so the equivalent of what would be called on a class in java or C sharp rather than an instance. That will teach me to comment at midnight :) And the rust term I think is Associated function (which is what I actually meant to write)
@FiosQuest
@FiosQuest Месяц назад
Ah yes, quite right! I should be careful to use the correct terminology. ☺️
@user-ut4hj7kc1t
@user-ut4hj7kc1t Месяц назад
Interesting topic, thank you. I would like to see more examples or use cases of it.
@user-ut4hj7kc1t
@user-ut4hj7kc1t Месяц назад
This rythmic music makes me hard to focus on a topic.
@Kampouse
@Kampouse Месяц назад
Gold ❤️❤️ shareing this!
@sheilabarnes7181
@sheilabarnes7181 Месяц назад
Good luck with that Daniel. I am sure you will do well with this. Great videos 🙏
@vighnesh153
@vighnesh153 Месяц назад
Good video. One point that I like to use in favor of Fakes or Stubs is that if you combine this with Dependency injection, then swapping the implementation is really simple. For unit tests, you can inject an InMemory implementation and for integration tests or functional tests, you could swap it with a local test server implementation or a remote server implementation. This way, you don't need to spend a lot of time writing more integration tests. Second, I think the word Adapter is used differently in the design patterns world. Adapter is something that helps objects with different interfaces collaborate with each other. The thing that you discussed in the video is often referred to as a Fake (provided by author) or simply a Stub (a tiny implementation of the interface typically done by consumer).
@FiosQuest
@FiosQuest Месяц назад
Thank you. To clarify, stub adaptors work with dependency injection arguably better than mocks/fakes. Since they use interfaces (or your language's variant) they guarantee type safety and since you can send them through the same integration tests as anything else that implements that interface they are also guaranteed to behave the same. Mocks in most languages guarantee neither. The wording stub adaptor was chosen because they are adaptors in hexagonal architecture terms but stubs because they don't actually reach out to an external service.
@Winnetou17
@Winnetou17 18 дней назад
Good point on the Adapter word! Also, don't forget to swap the adapters to the stub ones in production too, massive speed increase :D
@candyboober
@candyboober Месяц назад
I don't get it. stubs are mocks without calls tracking, so 0 benefits. integration tests are better for starting a project by many reasons, the most important ones: 1) the external interface change less often so we don't need to rewrite them every day; 2) they actually test the app, not a component. how come ddd helped Im confused, sounds to me like a cunt in a jacket - 0 relations
@thatguy2567
@thatguy2567 Месяц назад
As you said, the behavior abstraction might be wrong. Then don't abstract it. Your `StubUserStore` class just masks the actual code you _should_ be testing. Your tests are brittle not because of mocking, but because you're mocking the wrong thing. Mock `db: Database`. Mocking that and implementing the return of `db.select()` differently for each test to cover all return cases is what's going to give you non-brittle tests. Rule of thumb: only mock the parts that talk to the outside world. `db`, `fetch`, `localStorage`, etc. Mocking anything else is just a waste of time
@FiosQuest
@FiosQuest Месяц назад
Hi thanks for the comment but I'm not sure I follow: > the behavior abstraction might be wrong Solving this is addressed in the video, just throw it at the same integration tests as your DB/API/whatever implementation > Then don't abstract it Mocking is still abstraction > Your `StubUserStore` class just masks the actual code you should be testing I think you've maybe misunderstood. We're not masking the PostgresUserStore because that is tested in the integration test. StubUserStore is there to be used inside of other things you're testing. The thing we're testing in this example is the firstTimeUser function. You should not be testing any version of the user store in the tests for firstTimeUser. > Mock `db: Database` This just moves the mocking somewhere else, it doesn't solve the problems with mocking outlined in the talk. Some libraries provide mock versions of things like db instances. In theory this should be fine (never test a library), but in practice subtle differences mean that they aren't perfectly reliable. That said though, I've used this exact technique to provide stub adaptors in API libraries for people to use as stand ins so they don't have to create their own and can rely on the fact that they're run through the same integration tests as the version that talks to the API. If someone has done this you should be good to use that instead. Mocking db.select as you've suggested falls right back into the same problems with mocking I outlined in the video. > Rule of thumb: only mock the parts that talk to the outside world. Quite right, but where is your outside world? In DDD external libraries are outside of your domain, isolating your adaptors and stubbing those to inject into code that's actually being tested reduces the amount of code being run during testing significantly, while keeping your test coverage the same. --- The issue isn't what's being mocked, mocking is the fundamental issue. This technique provides solutions to the problems created by mocking, requires less work to implement, has more use cases beyond testing and is more stable and reliable.
@mantovani96
@mantovani96 Месяц назад
Exactly, sometimes you need to handle specific errors in your business logic and with mocking you can achieve that. Unit testing without mocking in a real application is almost impossible. Another point is, where you call “mockImplementation” you get type safe returns, meaning that if the method signature of the mocked object changes, all tests based on that mock will fail.
@thatguy2567
@thatguy2567 Месяц назад
@@FiosQuest > We're not masking the PostgresUser Store because that is tested in the integration test. StubUserStore is there to be used inside of other things you're testing. The thing we're testing in this example is the firstTimeUser function. You should not be testing any version of the user store in the tests for firstTimeUser. Then you're over testing. Just do the integration tests
@FiosQuest
@FiosQuest Месяц назад
​@@mantovani96 I'm sorry, I think you've misunderstood the video. Stub adaptors are stand ins for mocks. They perform the same job, can themselves be tested, are easier to write and maintain and can be used outside of tests. > you need to handle specific errors in your business logic and with mocking you can achieve that That is achieved with stub adaptors too. > Unit testing without mocking in a real application is almost impossible. I just showed you how this is possible... Stub adaptors are a complete replacement for mocks. > type safe returns, meaning that if the method signature of the mocked object changes, all tests based on that mock will fail. You get that with stub adaptors too because that's how interfaces/traits/et al work, however with stub adaptors your tests will fail if the behaviour of the stub adaptor diverges from the behaviour of any non-stub adaptors which doesn't happen with mocks... which was the entire point this video was making.
@phillduffy
@phillduffy Месяц назад
Useful video, thanks Rust Videos... good Test Videos... good
@FiosQuest
@FiosQuest Месяц назад
Thank you! 😊
@EightNineOne
@EightNineOne Месяц назад
WOOOO
@FiosQuest
@FiosQuest Месяц назад
Ooph! I've really got to work on how much I say "ummm". 😅
@delta4v
@delta4v Месяц назад
You should split this video to multiple parts. I feel like there are still a lot of use case of each expression with let or nested all of them together. It’s hard for rust beginners like me to keep up (even though I have 4 years in the industry) But amazing video🎉
@LoZander
@LoZander 2 месяца назад
I really like how you introduce Rust features and patterns in relation to each other instead of in isolation. There's a natural flow to how one leads to the other
@FiosQuest
@FiosQuest 2 месяца назад
Thank you! This one came together really naturally, but idioms and patterns are something I'm keeping my eye out for :)
@LoZander
@LoZander 2 месяца назад
very nice introduction to impl, generics and type state pattern (does this fall under that?)! If you always want a cat to be in one of these moods, another approach could be to inverse the model by making the cat type generic with a "mood". Then you can impl sleep only on Cat<Hangry>. This would also make all the general cat behaviour accessible no matter mood. You could then restrict this mood generic to a mood trait which you only implement on the type states :D Ofc. the downside of this approach is that you lose the general state machine and would have to implement the transitions on each animal, if you wanted to use the pattern on multiple animals.
@FiosQuest
@FiosQuest 2 месяца назад
Shh, you'll spoil the next one 😅 You are absolutely right but you can keep the default behaviour with Traits 😉
@LoZander
@LoZander 2 месяца назад
@@FiosQuest sorry 😅😂 But im sure you'll put it much more eloquently than I 😊
@LoZander
@LoZander 2 месяца назад
@@FiosQuest im looking forward to seeing the next one and how you use traits in it 😄
@FiosQuest
@FiosQuest 2 месяца назад
@@LoZander Haha, nothing to be sorry about, I'm delighted its gelling with you 😅
@Indrini-in6lm
@Indrini-in6lm 2 месяца назад
Great video! Love the shirt! ❤
@FiosQuest
@FiosQuest 2 месяца назад
Thank you!! I wasn't sure how it would go down as it's quite flowery but I love it too!
@FiosQuest
@FiosQuest 2 месяца назад
Thumbnail updated! Apologies if anyone ended up here having never heard of the old channel name and thinking I was saying the Rust language was dead 😳🤦🏻‍♂
@j-p-d-e-v
@j-p-d-e-v 2 месяца назад
Ive been studying Rust since January and based on my experience, LIFETIMES is the topic Im actually struggling with. Looking forward in your future contents. Hope you can make a lot of contents about lifetimes hehe :)
@FiosQuest
@FiosQuest 2 месяца назад
Hiya 👋 Thanks for the comment! Not sure if you saw but I did an introduction to Lifetimes in this video: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-nzDhYTtsZ-Y.html I imagine we'll cover them more as we move into things like concurrency though. We'll have to cover things like RCs, ARCs and Mutexes at some point too!
@j-p-d-e-v
@j-p-d-e-v 2 месяца назад
@@FiosQuest ahh yes I watched it before though I somehow cant apply it to complex lifetimes usage life in Serde. Maybe its a skill issue on my end 😅😅😅😅😅😅
@FiosQuest
@FiosQuest 2 месяца назад
@@j-p-d-e-v I don't believe in skill issues 😅 Not everyone thinks about things in the same way, and you're not the only person who's let me know they still don't understand lifetimes after seeing that, they're not easy! We'll think of other ways to mentally model it eventually. For Serde though, _if_ what you're trying to do is something like take a String and parse it into an object containing any number of &strs, you can do this but you need to make sure the String outlives the object. It doesn't matter how many references there are, as they all tie back to the original bit of data. struct Name<'a> { first: &'a str, last: &'a str, } If that's not it, feel free to pop into the Discord and we can chat about it in more detail 😊
@es05-03
@es05-03 2 месяца назад
Please include Yuki in the videos as well... 😊❤
@FiosQuest
@FiosQuest 2 месяца назад
Unfortunately, only Yuki knows when Yuki will be in a video 😹 (That said, *spoilers* I am planning to including him in the Traits video). Rest assured he's always busy behind the scenes, keeping me motivated. ❤
@LibreGlider
@LibreGlider 3 месяца назад
Sooo glad you mentioned that code coverage was a terrible metric.
@sheilabarnes7181
@sheilabarnes7181 3 месяца назад
Totally agree, sharing is caring. Very informative video, keep up the good work 😊
@FiosQuest
@FiosQuest 3 месяца назад
We grow together!
@LibreGlider
@LibreGlider 3 месяца назад
The tooling alone is enough. If you've ever had to do the make/cmake build dance, cargo and rustup is heaven.
@FiosQuest
@FiosQuest 3 месяца назад
Oh my gosh yes! To be fair though, Rust has learned huuuge amounts from tooling from older languages. Also, while Make is 48 years old I actually still use it... even in my Rust projects, depending on what I'm doing. 😅 It's quite nice for things like Dioxus for example, or more complex Docker stuff with PHONY targets (though there might well be a better way of doing both of those 😛).
@LoZander
@LoZander 3 месяца назад
I really liked this tutorial! I thought it might have been interesting to also motivate ownership by showing how singular ownership circumvents dangling pointers, but I that might be more detail than is required to understand how it works. I really liked your kite analogy as well :D
@FiosQuest
@FiosQuest 3 месяца назад
Thank you, it literally took me seven years to come up with that analogy. 😅 You're right, there's so many ways in which lifetimes, challenging as they are, are awesome, but with people coming to these videos from all sorts of languages (and even a few non programmers which is awesome) I wanted to keep it as simple as possible. My hope is that people who know about lower level languages recognise the benefits like this, and that those who don't, never have to find out. 😅
@LoZander
@LoZander 3 месяца назад
@@FiosQuest yes, that makes a lot of sense. Keep on doing the good work :D Also, I'm curious on why you advice against passing mutable references to functions? Usually I'd agree, but specifically because of the implicitness of a function changing a value which exists somewhere else, but in Rust it's rather explicit. Maybe there's something I'm missing or an entirely different reason that it's not good practice generally? :)
@FiosQuest
@FiosQuest 3 месяца назад
​@@LoZander I might have come off a bit strong in this video, but I'm not saying never do it. In fact, for the homework, you'll need to. 😉 More just "attempt" to avoid it, both for legibility / grokability, and for being more intentional around memory management. For example, if you need to read and modify something, that's fine. Even something as simple as Vec::reverse(&mut self) is a good use of a mutable reference rather than assign a bunch more memory for your reversed vector. But often times a mutable reference can cause subtle issues with memory management. For example, in my opinion, StdIn::read_line ( doc.rust-lang.org/std/io/struct.Stdin.html#method.read_line ) is almost never going to be the right way to access standard in _unless_ you need to append the input to the given String, and even then, you're _probably_ going to cause Rust to allocate new memory and move all the data anyway, you just _might_ get lucky and there's enough capacity in the String to avoid that. None the less, that's how the official book ( doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html ) suggests you get input from standard in, with String::new of all things. Funnily enough this actually won't cause an extra allocation unless the user enters something unexpected in this use-case, but (IMO) we're teaching people bad habits early here, which is why I used .lines() in my version. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-6PQ8kx2ZFv0.html
@FiosQuest
@FiosQuest 3 месяца назад
@@LoZander These are great questions by the way, thank you. :)
@LoZander
@LoZander 3 месяца назад
@@FiosQuest Ofc., and thank you for your answers :D I'm not sure I'm completely understanding why the mutable reference specifically is the issue in the example you mention. Is it that the mutability might indicate that the function will do some operation on the data which will cause inefficient memory operations? Like it's a mutability issue wherein its best to evoid mutating generally? Or is it a mutable *reference* specific thing that I'm not getting? Thanks you for your answers :)
@SelectedPeppa
@SelectedPeppa 3 месяца назад
great videos. U lost me wth that lifetime stuff, but thats me beeing old and stupid. The only thing that I want to critique is the music. It gives the video a nice touch, but it is a little bit distracting when you talk over the music. maybe fade it out when talking? Dunno... keep up the great work!
@FiosQuest
@FiosQuest 3 месяца назад
Thanks for the feedback! Levelling the music is really difficult, it sounds different on everything you listen to on. If I ever stitch these videos together you'll see they're all over the place too. 😅 Oh dear, I was so pleased with my lifetimes metaphor too 😅 I was going to make it a Short, but I'll have a think about how I can tighten it up. It's definitely not you, lifetimes are the hardest thing in Rust to learn, but I know you can do it! If it helps at all, I _used_ to think of it upside down. The data is owned by a ship, the anchor is a reference and the chain joining it back to the ship is the lifetime. Wherever the chain goes, its always connected back to the ship. The reason we need to annotate them is just so we know which anchor is tied to which ship. If the anchor enters a... umm... function (oh dear) where it isn't certain which anchor is coming out, it can only go as far as the nearest ship in the... erm... stack (yeah none of these metaphors are perfect) 😅 Either way I'm sure you'll find a mental model that works for you, and if you do, please share it back with me! The more ways we can describe something the more it'll help other people.
@SelectedPeppa
@SelectedPeppa 3 месяца назад
@@FiosQuest hey thanks for the effort. You are really helpful. I'll work through my rust book and through your videos, step by step . I'll probably rewatch this one once I have a basic understanding. Thanks for all yor time and effort.
@RaduMarias
@RaduMarias 3 месяца назад
hey, informative video. could you please tell me what the VSCode theme used in the video?
@FiosQuest
@FiosQuest 3 месяца назад
Hi Radu! Thanks very much. The theme is great, right!? It was made by a good friend of mine. Its called "Urple" and is part of the Ashokia theme pack you can find here. marketplace.visualstudio.com/items?itemName=Teriyaki.ashokai
@FiosQuest
@FiosQuest 3 месяца назад
Erratum and other interesting things ============================= I'm definitely going to make mistakes as I make these, I'll pin a comment with anything important. If you spot anything not mentioned here, let me know so I can add it! Homework Code --------------------------- I noticed after uploading that _one_ of the code samples in the homework section shows a different method of working out if the first letter is valid. Decided to keep it as it might actually be simpler than the one I went with in the end. 😅 Trousers -------------- I did _not_ like how they looked so tried to zoom myself in enough to hide them in most shots. After my shirt in a previous video I'm seriously thinking I might need someone to dress me for these. 😅
@astrakernel
@astrakernel 3 месяца назад
Awesome tutorials, keep up the good work
@FiosQuest
@FiosQuest 3 месяца назад
Thank you! I'm probably going to have to work this around a proper job soon but we'll see how it goes. 😅
@EightNineOne
@EightNineOne 3 месяца назад
The next part is where things get really spicy.
@FiosQuest
@FiosQuest 3 месяца назад
Aw yeah! I can't wait 😅
@opless
@opless 4 месяца назад
AFE says hi! Not testing is mostly dangerous 😉
@FiosQuest
@FiosQuest 3 месяца назад
Hiya 👋🏻 hope you're doing well 😊
@opless
@opless 3 месяца назад
@@FiosQuest doing wonderfully. Missed the notification on this one 🤣
@martingeorgiev999
@martingeorgiev999 4 месяца назад
Great video. Your channel looks very promising.
@FiosQuest
@FiosQuest 4 месяца назад
Thank you so much! If you're interested in what's coming up, it's roughly planned in the chapters of the book. 😊
@FiosQuest
@FiosQuest 4 месяца назад
Erratum and other interesting things ============================= I'm definitely going to make mistakes as I make these, I'll pin a comment with anything important. If you spot anything not mentioned here, let me know so I can add it! ⚠ Homework Mistake -------------------------------------- Skip the second requirement, maintaining the first capital. It was _waaaay_ harder than I expected. This is especially daft because I talked about how capital letters are more complicated than you'd think _in this video_! I do talk about how to do it in the next video but it requires a lot more dealing with iterators which we still haven't really covered yet. Homework Clarification -------------------------------------- Approach the homework one task at a time. Take the first requirement, write the test, make the test pass, then add a test for the second requirement, etc. When to use E2E tests ----------------------------------- I didn't want to delve too deep into this in the video, but E2E tests really should be kept to a minimum. I've worked at a lot of places that get this wrong. E2E tests should _only_ test critical happy paths of software, and if you've got good coverage of unit and integration tests, this is all you need. Not only to E2E tests take a long time, and provide bad coverage, they can also be flaky (sometimes passing, sometimes not) and brittle (they stop working for minor changes). This often leads them to being somewhat ignored. I once worked at a place that ran over 300 unit tests, which took nearly 4 hours to complete, and every time around 3 tests would fail... but which 3. 🤔 This kind of testing is completely pointless, it's often done because it feels like we're "covering" loads of code at once, but we aren't, we end up with no idea if a change is causing a real problem or not. Keep E2E tests to a minimum and make sure they pass every time. Palindromes -------------------- I said a word that's the same backwards or forwards, that's not even true in the context of this video 😅 A palindrome is "a word, phrase, or sequence that reads the same backwards as forwards" Take ------- In our `is_palindrome()` function, we could use `.take()` to only take half the characters rounded down of each iterator (once we've checked half way through the word, if its already ok, the second half is the same checks in reverse). We'd only need to apply this to the forward iterator like this: ``` forward.take(input.chars().count()).zip(backward).all(|(f, b)| f == b) ``` However, firstly I thought this is too complicated, and secondly, I'm not sure this is better. Doing this _might_ introduce more comparisons and branches in the code which _might_ mean it actually slows the function down. If we cared about performance here then I would benchmark the two variations. If we don't care about performance, then go with the easier to read code. Engineers are expensive, and CPUs are not, so don't waste time with unnecessary optimisation, but, when you do need optimisation always measure. Reverse Iterator of Chars ---------------------------------------- I just thought this was interesting. The `.chars()` method returns the `Chars` type. This is _basically_ and `Iterator<Item = Char>` _except_ that it also provides the method `.as_str()`. Once we reverse it, you do get an `Iterator<Item = Char>` which doesn't provide this method. Boom! ----------- I did not, in fact, get it right the first time. There's a mistake. Can you spot it (note: you'll need to check the book)? 😅 In Jokes ------------- I ended up spending too long on an "in joke" that <1% of my audience will get. Editing it took ages, but I learned a lot about delta keyers, magic masks, garbage mattes, solid mattes, and even roto scoping, all of which is used in those sequences. 🤯 So... it was worth it for me at least. 😅 I don't think I'll do something that hard again, but I was happy Indra could join me.
@sheilabarnes7181
@sheilabarnes7181 4 месяца назад
Another brilliant presentation Daniel.. Hi Yuki♥️
@FiosQuest
@FiosQuest 4 месяца назад
Thank you! Yuki says hi back 😸
@FiosQuest
@FiosQuest 4 месяца назад
Erratum and Ellaboration: ===================== I'm definitely going to make mistakes as I make these, I'll pin a comment with anything important. If you spot anything not mentioned here, let me know so I can add it! format! ------------ You don't need to store the result of the format macro in a variable before returning it, and in the script I spent time pointing this out. I dropped it in edit though as I thought the annotations that VSCode adds really help show what's happening. Heap Memory Management --------------------------------------------- Usually the operating system provides memory management, but this isn't always the case. Its possible to write your own memory manager in Rust and this is typically what happens when writing for web assembly or embedded systems where the OS isn't directly available or completely non existent. Big negative impacts on performance ------------------------------------------------------------ I didn't meant to single out Go here, that's just the title of the blog article. You can find similar issues in most (all?) garbage collected languages, but that's not to say these are bad languages. Usually these languages have specific use cases in mind, and they perform fantastically at them. I wouldn't even say Discord necessarily chose the wrong language to start with, the service that they changed was doing its job and doing your job is what makes money. Remember, perfection is the enemy of done. Don't fret _too much_ about what language is the best, choose the one that gets your project up and running adequately the fastest. Copy from the Heap -------------------------------- It is totally possible to put Copy values on the Heap (using a type called Box), and there are reasons you might do this to do with dynamic dispatch. Since we aren't going to cover dynamic dispatch for a while, not to mention, reasons to have to do this are vanishingly small, I didn't really want to delve into this but in hind sight there might have been a better way to word this, or at least I could have said "almost always". You still have to copy the inner value of the Box though, Box itself is not Copy ⚠ Mistake in Split with Substring ------------------------------------------------------- This one is important as it'll impact the homework. In the function, the second slice starts at [found_at + 1 ..] This is wrong, if your sub_string is longer than one byte it won't give you the correct result. 🤦🏻‍♂ It should be [found_at + sub_string.len() ..] Borrow ----------- Never really explained this but when you pass a reference to data that is owned elsewhere, you are "borrowing" it. You'll see "reference" and "borrow" used somewhat interchangeably throughout the Rust ecosystem. If anyone would like to elaborate on this, please drop a reply :)
@crazyingenieur3277
@crazyingenieur3277 4 месяца назад
I am pretty sure the max value of i64 is not 127.
@FiosQuest
@FiosQuest 4 месяца назад
Dang, good spot! 😅 Not a lot I can do about the video, but I've corrected the IRISS book, and will add it to the erratum. Thank you!
@Liam-ze3ii
@Liam-ze3ii 4 месяца назад
感谢,期待更细~
@Liam-ze3ii
@Liam-ze3ii 4 месяца назад
期待更新
@FiosQuest
@FiosQuest 4 месяца назад
Thank you! I'm working on the next one now, and hope it'll be out soon 🤞🏻
@riigel
@riigel 5 месяцев назад
excited to understand lifetimes!
@FiosQuest
@FiosQuest 5 месяцев назад
Thanks! I think lifetimes are actually really awesome, but perhaps poorly explained. It's taken me a good 7 years to come up with the analogy I'm going to use though so it's hardly a trivial concept.
@FiosQuest
@FiosQuest 5 месяцев назад
Erratum: ======= I'm definitely going to make mistakes as I make these, I'll pin a comment with anything important. If you spot anything not mentioned here, let me know so I can add it! 🙏🏻 That shirt --------------- Since I'm trying to list all my mistakes 😅 Float values in match ---------------------------------- This is actually a really bad idea as floats should never be used for "exactly equals", and in fact is a deprecated feature of Rust causing a compilation warning. Using floats with things like greater than or less than in match guards is fine You can use integers and chars for exact value matches in match though.
@riigel
@riigel 5 месяцев назад
More! really great content! thanks for this!
@FiosQuest
@FiosQuest 5 месяцев назад
Thank you so much. 😊
@xav_624
@xav_624 5 месяцев назад
Your binary explanation is 👌👌😍
@FiosQuest
@FiosQuest 5 месяцев назад
Thanks! I was really worried actually, the entire point of this series is to help get rid of the "Rust is hard" stigma and I've jumped straight to memory and binary, how many programming tutorials start there?! 😊 However, I think it's important to set up that foundation, it's going to make everything else much easier, and just because many tutorials don't start with low level foundational stuff doesn't mean its necessarily hard or uninteresting. It's not _easy_, sure, but I think people will get it. 🤞🏻 And I'll do my best to answer questions where I might have missed something or where I've not connected in the right way.
@xav_624
@xav_624 5 месяцев назад
@@FiosQuest Definitly! I'm a frontend guy who wants to understand more and expend my field of action, and believe it or not, there's not much quality content on those fundamentals. I find it hard to find what I'm looking for. But I loved this. I'm looking forward for the following parts. Take care ✌
@RoyaltyInTraining.
@RoyaltyInTraining. 5 месяцев назад
I usually like to use my package manager for everything I can, so I don't have to keep track of multiple administration tools. Is there any downside to doing that instead of using rustup? I've been messing around with some stuff after using this installation method, and didn't run into any problems so far.
@FiosQuest
@FiosQuest 5 месяцев назад
What a great question! I don't think you'll run into any major issues, particularly while learning, use whatever feels right for you. Rust gets a minor update at least once every six weeks so if you want to stay on top and that's the easiest way to do it, you do you! Once you start getting deeper into Rust though, rustup offers some extra functionality that (afaik) you can't get from your distro's package manager. This includes being able to manage different compilation targets and toolchains, manage individual components within the Rust tool suite, easily switch between nightly and stable, pin versions for different projects, etc. I don't think we'll touch any of this in the IRISS series (so long as you can do `cargo test`, `cargo doc`, and `cargo clippy` you should be fine), but if you start doing professional Rust or collaborating with people on complex projects you _might_ need to swap to rustup. If you want to learn more about what Rustup offers and whether you need it, the documentation is a little hidden away but you can find it here: rust-lang.github.io/rustup/
@xav_624
@xav_624 5 месяцев назад
I'm IN!! Good luck in your adventure 🙏
@FiosQuest
@FiosQuest 5 месяцев назад
Welcome and thank you!
@astrakernel
@astrakernel 5 месяцев назад
Good work, subscribed :)
@FiosQuest
@FiosQuest 5 месяцев назад
Thank you! ❤️
@FiosQuest
@FiosQuest 5 месяцев назад
Erratum (and other fun stuff): ======================= I've got some small silly ones today, but if you spot anything I've missed, please let me know so I can add them and we can help make this better! 💖 ASCII --------- The character encoding I mention in the Binary primer is called ASCII but there are 128 characters, not 127 (I forgot zero 🤦🏻‍♂). There are also control characters in ASCII which are characters that tell the computer to do something but are otherwise effectively invisible. Nybble ----------- Discovered this gem while editing. 4 bits (half a byte) is sometimes referred to as a nybble. That makes each hexadecimal digit a nybble. Not useful, just cute. 🥰 Negative Zero ---------------------- Another weird one I found while editing, there's another numbering scheme for integers called One's Complement. It works a bit differently, but gives us numbers -127 to +127... and both +0 and -0. Thank goodness we don't use that, having to deal with both positive and negative numbers would have been rough right float? ... Right float? (Float has positive and negative zero, positive and negative infinity and multiple values for "not a number"). Tuple --------- Oh the irony! I made a joke about not wanting to change my pronunciation on char, but a lot of people say "two-pl". This is because historically, it specifically represented two values _but_ in this case the correct pronunciation _is_ tuh-pl (but you will definitely hear it both ways and that's fine). The Unit Type ---------------------- I never closed the loop on this one 🤦🏻‍♂. I mentioned we often use the unit type () in Generics but never gave an example. Imagine a function which perhaps sends a message but doesn't get anything in return. We might want an Error type to explain what went wrong, but we'd use the unit type for the success value as the success itself is all we care about, eg: Result<(), SomeError> Memory Usage ------------------------ I feel like I made a bit of a fuss about how much memory various Types take up, but, you don't need to worry all that much. i64 Max ------------- As spotted by @crazyingenieur3277, the max value for i64 is "9,223,372,036,854,775,807" not "127"
@sheilabarnes7181
@sheilabarnes7181 6 месяцев назад
A brilliant presentation Daniel. Thank you.
@FiosQuest
@FiosQuest 6 месяцев назад
Thanks! This one was a toughy. 😅
@davidchristie8783
@davidchristie8783 6 месяцев назад
Yuki the director cat!
@FiosQuest
@FiosQuest 6 месяцев назад
He does tend to have a lot of notes for me! I just wish I understood them 😻
@joinvillecustodio
@joinvillecustodio 6 месяцев назад
"What do you mean, I'm your agent" 😂😄
@FiosQuest
@FiosQuest 6 месяцев назад
Erratum: ======= As ever, I'm going to make mistakes, please let me know what you spot and I'll try to write them up here so we can provide a better experience for newbie devs 💖 Standard Library -------------------------- I didn't really explain this. The Standard Library is a collection of useful data types, functions, etc. We will definitely talk about this more next video when we cover Option and Result in more detail, as well as collections like Vec and HashMap. All of these belong to the standard library. Option and Result ---------------------------- I really should have gone back to the code for the explanations here. If you're following along in VSCode with Rust Analyzer, or any other editor that over zealously annotates the types for you, you can see that it's added the type information for these, i.e. Option<Result<String, Error>>. Not going into more detail in this video, but I think it helps visualise what's happening. Tony Hoare ------------------ I feel really bad about this one. Tony Hoare is a legend who's been a huge contributor to the field of computer science. I don't want people to think that his only contribution was this one thing he called his "billion dollar mistake". The man has contributed more than enough back to the economy to cover this debt, believe me! "Contains the data" ------------------------------- I'm a little unhappy with the way I've phrased this. All high level languages including Rust, C, C++, etc, are abstractions over what's really happening on the stack, and are not 1:1. What "contains" the data is a bit moot, and I regret emphasising it this way. Where the data lives is correct though.
@arunas1
@arunas1 6 месяцев назад
supporting with subs & likes a fellow rustacian ;-)
@FiosQuest
@FiosQuest 6 месяцев назад
Thank you! I hope its useful
@FiosQuest
@FiosQuest 6 месяцев назад
Erratum: ======= I'm definitely going to make mistakes as I make these, I'll pin a comment with anything important. If you spot anything not mentioned here, let me know so I can add it! 🙏🏻 Semicolons! -------------------- Something I can not believe I missed, I didn't mention semicolons! 🤦🏻‍♂ The reason this surprises me so much is that semicolons are an important part of one of my favourite language features, expressions! A line of code in Rust is called a statement, and in Rust there are two types of statements, expressions and declarations. Expressions have a value, declarations set a value. You can combine expressions with both other expressions (building a larger value) or a declaration (its the value that you set in the declaration). Eg, in the declaration `let name = "Daniel"` the expression is "Daniel". This leads to some _really_ cool abilities like being able to return a value from flow control statements like if, match and various loops. We'll cover how expressions interact with flow control in a future episode (either before or after functions, not sure yet). For now, all you need to know is that you need to break statements up with a semicolon`;`.
@weiSane
@weiSane 6 месяцев назад
I see rust I sub 🫡
@FiosQuest
@FiosQuest 6 месяцев назад
Haha, I'm the same!