📝Get your *FREE Rust cheat sheet* : www.letsgetrusty.com/cheatsheet
@jaysistar27112 жыл бұрын
Yes, more functional programming in Rust videos, please!
@naughtrussel57872 жыл бұрын
I'd like to see more videos about functional programming in Rust. I personally do not program in Rust, but the concepts you teach are extremely useful for a programmer of any language.
@Zytaco2 жыл бұрын
Your non combinator code can be made a lot prettier by not using is_some() methods. Instead use an if let. For example: if let Some(name) = s.next() { //Do what you want here. } This checks if there's a name and immediately puts it in the the variable 'name' on the same line. Sadly, if let chains are not yet stable so you can't do these multiple times in the same if statement. (Although you can on nightly rust.) But you can still use match statements like: match (s.next(), s.next()) { (Some(name), Some(gpa) => { //Do what you want here. }, _ => (). }
@tomaspecl10822 жыл бұрын
You can write if let (Some(name),Some(gpa)) = (name,gpa) { /* code */ } You dont need match for this.
@alagaika85152 жыл бұрын
Also, the nested ifs can be avoided by negating them and using continue for the cases where the student in question is not a good student.
@canewsin2 жыл бұрын
instead for map.flatten.filter, filter_map can do it with single combinator.
@maximebeaudoin40132 жыл бұрын
Don't keep it to yourself, what's your suggestion?
@psychic-lizard2 жыл бұрын
@@maximebeaudoin4013Basically, filter_map accepts a closure that returns an Option. If an item returns the Some variant, it will keep the mapped item, but if it returns the None variant, it will be filtered out. It's basically like calling map that turns the elements into Option types, and then filtering out the None variants. The rust docs explain it much better than I can: doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map
@canewsin2 жыл бұрын
@@maximebeaudoin4013 > let students = vec!["Z 5", "A 10", "B 20", "C 30"]; let good_students = students .iter() .filter_map(|s| { let mut parts = s.split_whitespace(); let name = parts.next()?.to_owned(); let score = parts.next()?.parse::().unwrap(); if score
@31redorange082 жыл бұрын
@@canewsin unwrap() 🤔
@WolvericCatkin2 жыл бұрын
@@canewsin Just contributing my personal implementation... #[derive(Debug)] struct Student {name: String, gpa: u8} let students = vec!["A 5", "B 10", "C 15", "D 20"]; let good_students: Vec = students.iter() .filter_map(|x|{ let mut x = x.split_whitespace(); let name = x.next()?; let gpa = x.next() .and_then(|gpa|gpa.parse().ok()) .filter(|&gpa|gpa > 10)?; let name = name.to_owned(); Some(Student{name, gpa}) }) .collect(); good_students.iter() .for_each(|x|println!("{:?}", x));
@codetothemoon2 жыл бұрын
Definitely up for more FP Rust videos!
@adamhenriksson60072 жыл бұрын
In rust there is a difference in performance between the first and second method depending on how you design combinators. You should show if this code is as perfromant as the first piece of code. Sometimes it's also more perfromant because of vectorization, but that also does not always happen.
@UltimateMonkeyman2 жыл бұрын
would like to see performance comparison for with vs without combinators as well. cheers
@ibrahimshehuibrahim9182 жыл бұрын
i think rust has zero cost abstraction similar to c++
@adamhenriksson60072 жыл бұрын
@@ibrahimshehuibrahim918 yeah but that is a compiler optimization. Not sure if this applies in all cases or just the more common/trivial cases.
@G117132 жыл бұрын
The combinator code could also be optimized such as into a bunch of maps and/or delay creation of the Students structure until after the filter. Of course, who knows how the compiler optimization might evolve the code.
@yoannguillard68772 жыл бұрын
As far as I know combinators are more optimized concerning the array. It will statically allocate the right size for the array, which requires to use everytime a capacitor if you do it sequencially
@JayKnight2 жыл бұрын
I started learning rust with Advent of Code, and I wish I had seen this video earlier. More than half of my time was spent figuring out how to parse the input into the structure I needed!
@artgocode2 жыл бұрын
Thank you so much! Your content is concise and very helpful for newbies.
@Maartz2 жыл бұрын
Coming from Elixir/Erlang, it's sweet to see that Rust has a nice FP side. Thanks for the video! Love it.
@JayGodseOnPlus2 жыл бұрын
As with Rust, one of the early language designers of Elixir is also a Ruby guy (Jose Valim, I believe).
@Maartz2 жыл бұрын
@@JayGodseOnPlus yes indeed! I didn’t knew that one designer of Rust was coming from Ruby. But definitely you can feel the FP touch in Rust and it’s delightful.
@SebastianSastre2 жыл бұрын
Now I know that in Smalltalk I never use anything that isn't a combinator. And now I know how to preserve that good style in Rust. That was awesome, thanks for sharing this.
@MrTact67 Жыл бұрын
Nice! Only thing I would do differently would be to impl From (or maybe even &&str) on Student and move that conversion logic into there.
@BetadeskСағат бұрын
How would that work if the string is malformed? As far as I can tell the From trait would have to return a Student and can't return Option
@HUEHUEUHEPony2 жыл бұрын
thats not combinator thats just functional programming
@jeffg46862 жыл бұрын
+1 for flatten()ing Option based iterators - hadn't come across that yet. I had previously thought it was only purposed for flattening nested iterables
@durnsidh64832 жыл бұрын
Option is an iterable, if it's a Some variant it returns Some(value) followed by None, otherwise it returns None.
@jeffg46862 жыл бұрын
@@durnsidh6483 - interesting, thanks.
@mathmage4202 жыл бұрын
I almost never use for loops now that I've gotten used to functional programming with Rust. Parsing data is really easy to do with functional programming.
@oyewodayo2 жыл бұрын
I so much appreciate videos with use-cases like this. Do more of this please. Thanks.
@theondono2 жыл бұрын
Pro tip: if you have a struct with a lot of booleans (think something like a config). Instead of having a “new” function with dozens of parameters, set new to return a config with all booleans to false. Then create combinators to set each variable. You can then just chain the ones that need to be set after your new call. Much more ergonomic and the compiler will optimize the calls away. 👌
@letsgetrusty2 жыл бұрын
Awesome tip!
@theondono Жыл бұрын
@@marcyeo1 Yes, but the point of the tip was making them chain-able. Instead of having: let config = Config::new(); config.flag1(true); config.flag2(true); config.flag3(false); config.flag4(true); You have: let config = Config::new() .flag1(true) .flag2(true) .flag4(true); Depending on your flags and their names, it also makes a lot more of sense to talk about the properties something has, than on those it doesn't.
@bencarville1045 Жыл бұрын
@@theondono I would prefer to `impl Default for Config` and then let config = Config { flag1: true, flag2: true, flag4: true, ..default() } so you don't have to define a method for each flag.
@theondono Жыл бұрын
@@bencarville1045 I’ve also used this option. I’m realizing too that I explained mine particularly badly, because the point of it is to avoid having the boolean values in the first place. What I should have written is something in the lines of: let cat = Cat::new() .has_stripes() .has_sharp_claws() .has_temper(); Where all of this options are booleans that are set to false by default. In this scenario you just add the features you want the cat to have, and avoid having to write anything about the ones it doesn’t, so that reduces visual clutter IMO. It also completely hides the actual “polarity” of the Boolean used in case it’s useful internally.
@BetadeskСағат бұрын
Rustaceans rediscover the builder pattern
@manis0us2 жыл бұрын
Thanks, please add more functional programming concepts in rust.
@BenHawkins182 жыл бұрын
I would LOVE to see more functional rust!!
@hmbil6942 жыл бұрын
This is really cool I’d love to see more functional rust stuff!
@cramhead2 жыл бұрын
Great vid! More functional and idiomatic programming content please. These bite sized vids are great as they are easy to fit into a packed schedule.
@mateusvmv2 жыл бұрын
You could also have used flat_map, as it does what map, flatten and filter are supposed to do all at once!
@MartinClausen Жыл бұрын
Great stuff, would love to see more functional rust videos.
@user-if7lb8zy8i2 жыл бұрын
you didn't say lets get rusty :(
@letsgetrusty2 жыл бұрын
🙈
@eduingarciacordero92552 жыл бұрын
Very good. This flatten function change everything. Thank's
@Amejonah2 жыл бұрын
3:30 why no if let?
@hongotopiadada75742 жыл бұрын
I loved that video and it would be awesome to see more stuff about combinators! thx
@epiderpski2 жыл бұрын
coming from languages that don't use combinators, so this was very helpful. Thanks!
@Tferdz2 жыл бұрын
You could use guard clauses to avoid nesting the first part
@JayGodseOnPlus2 жыл бұрын
I'd love to see more such videos of functional programming using combinators, especially using map, reduce, and filter. And then show it using the Rayon crate to harness multiple cores in parallel.
@SuperQuwertz11 ай бұрын
Great tutorial! Thank you!
@MrPetzold123 Жыл бұрын
This was nice ! Much harder was when I tried to find the best student using iterators and GPA, because f32 doesn't implement Ord due to floats being weird :-). Edit: and Rust does not allow half-bakedness...
@STatic40092 жыл бұрын
Oh... this is how I would do the equivalent list comprehensions in python. Excellent video!
@empeaTV2 жыл бұрын
Pretty good channel Bogdan. Keep it going. Cheatsheet is great as well.
@DougFort2 жыл бұрын
+1 for functional rust
@joelmontesdeoca65722 жыл бұрын
Would love a series in functional programming. 👍🏼👍🏼👋🏼
@josemanuelberrios73902 жыл бұрын
Thank you!! This is so awesome
@jonathanmoore56192 жыл бұрын
Beautiful. Yep more please.
@diegof40832 жыл бұрын
Nice, but flatmap will help you instead of map + flatten
@khai96x2 жыл бұрын
For Option, I prefer filter_map.
@diegof40832 жыл бұрын
@@khai96x Great
@alxjones2 жыл бұрын
Both flat_map and filter_map will work, but filter_map has size hints because the result is guaranteed to be bounded above by the input size, while flat_map may increase size without bound in general (such as a nested vec structure). So, they're not functionally identical but practically identical for most purposes. That said, readers from other languages will probably appreciate a distinction being made between the two, as most languages don't have as robust a flat map combinator as Rust does.
@Blure2 жыл бұрын
Thanks for sharing your knowledge mate. May I ask what's the plugin doing the floating diagnostics and inlay hints for types?
@eduingarciacordero92552 жыл бұрын
rust-analyzer. If you use vim you can use coc-rust-analyzer, is very good.
@iangithungo20442 жыл бұрын
rust analyzer vs code extension
@JTCF2 жыл бұрын
Didn't know what combinators are, but it turns out I've preferred to use them for a loooong time. Cool.
@abhikbanerjee37192 жыл бұрын
Which rust VS Code extension are you using in this tutorial?
@josemanuelberrios73902 жыл бұрын
Please make more videos about combinators!!!
@moiattube2 жыл бұрын
So clear explanation! Thanks a lot
@arroba32182 жыл бұрын
I'm happy I already knew these concepts coming from Javascript. Generally, I think it's good to filter before mapping.
@KohuGaly2 жыл бұрын
In this case, the filtering can only happen after parsing the string, and there's very little point in parsing the string twice. Technically you could save one allocation (for the name string) per rejected item, but that can also be achieved by mapping twice (first mapping returns (&str,f32) then filter, then second mapping converts &str to owned and creates the struct)
@arroba32182 жыл бұрын
@@KohuGaly That's a valid point.
@DipankarMajumder2 жыл бұрын
Thanks for demonstrating the functional paradigm... this looks much like JS/TS...
@altairbueno56372 жыл бұрын
I always forget that ? Works on optionals too
@ShreksSpliff2 жыл бұрын
I want a language support like rust has but only functions. Thanks for doing the better part of the basics.
@therealjezzyc62092 жыл бұрын
so haskell?
@mrocto3292 жыл бұрын
yeah you're asking for Haskell, it's an amazing language designed to be purely functional.
@yogabija2 жыл бұрын
Great video, more videos especially with functional coding techiques :-)
@soberhippie2 жыл бұрын
Great video, nice approach to map-reduce, different to that in Python. On an unrelated note, the way you say "cheat sheet" sounds like it is something Chinese probably spelt "QiXi" )
@duke6059 ай бұрын
Not sure it `filter_map` was a function when this video was created but `filter_map` would do the work of `map`, `flatten`, and `filter` all in one go
@bjugdbjk2 жыл бұрын
Just love it !! Do you have any pointers where all these combinators r available for read and trying it out ?
@emoutraspalavras-marloncou44592 жыл бұрын
Thanks Bogdan. We could have used for_each here to print out the result, couldn't we? But if I am not mistaking, in this case without storing the value in a variable and collecting the iteration outcome, right?
@EngineerNick2 жыл бұрын
yeeeesss the delicious iterators! Thankyou for the great video. If only rust was able to more easily pass uncollected iterators around between functions... Sometimes its possible I think possible but it often causes me trouble. I guess that's the price of compiling stuff and predictable memory layout etc
@chinoto12 жыл бұрын
Functions can accept and return `impl Iterator` and `Box`, which could resolve your issue without needing to state all the underlying types. impl Trait arguments can produce better optimized code through monomorphization, while Box is better if your functions will be accepting a variety of iterator types to avoid bloat in the executable.
@powerclan19102 жыл бұрын
i would like to see you make a larger project if possible at all ;)
@letcodeitnow2 жыл бұрын
Good content....What's the name of the extension that monitors your exception
@letsgetrusty2 жыл бұрын
Error Lens
@SamArmstrong-DrSammyD2 жыл бұрын
Could you run a reduce operation with unique ids to turn that into a hash map?
@GlobalYoung72 жыл бұрын
Thank you very much 🥳🙌
@bitflogger2 жыл бұрын
Great video! If your map function produces a vector with each iteration, how can you combine the returned vectors into one vector?
@KohuGaly2 жыл бұрын
Look at fold and reduce methods. In fact, I recommend you read the entire documentation on interators in standard library, and possibly in the itertools crate. Iterator (and option) combinators are so prevalent in rust, that it definitely pays off having a general overview of their features.
@beyaz14042 жыл бұрын
Really good presentation. Can you explain error management ?
@letsgetrusty2 жыл бұрын
On the list!
@cron3x2 жыл бұрын
nice Video, i will use this. could you make a video about the VSCode Extensions you have? that would be cool
@anindyasundarmanna66832 жыл бұрын
I have to say, the point of readability feels biased. The later has advantages like being concise, bit more performant maybe. But is it really MORE readable and easy to understand, specially to a beginner?? I'm not so sure. Great video as always! :)
@bjugdbjk2 жыл бұрын
More of functional programming !!
@usmanmughal59162 жыл бұрын
Which extension do you use for the highlighting of data types?
@joeybf2 жыл бұрын
It looks like rust-analyzer
@jeanehu-pludain66402 жыл бұрын
but which speedess ?
@xrafter2 жыл бұрын
What's a combonator?
@Yotanido2 жыл бұрын
I'm not a big fan of the if is_some and unwrap pattern. With later refactorings, you might accidentally remove that check and then end up panicking. Much better to use if let instead.
@MichaelZimmermann2 жыл бұрын
My experience is that most of the time these are superior in readability but that you shouldn't try to force it since they can start looking insane if you overdo it 😁
@ixion2001kx76 Жыл бұрын
8:16 no that is not a lot cleaner. That’s a chain of mysteries for future programmers to wrap their heads around.
@doomguy62962 жыл бұрын
Yes. More functional programming.
@flogginga_dead_horse40222 жыл бұрын
Great content
@jackwells98932 жыл бұрын
Great video
@kovalenkokirill2 жыл бұрын
great videos, thank you! may i ask something off topic? i somewhat interested in languages and linguistic and have a question. why do you pronounce some ST words such as struct and string as SHtruct and SHtring, while in some other cases such as student, start, stop, you don't make SH (Ш/Щ) sound? what is the origin of this?
@scotty30242 жыл бұрын
To everyone here saying he should have used filter_map. You forget about the separation of concerns that he's trying to make, the map is converting the iter, then the filter is another concern that does another thing.
@emvdl2 жыл бұрын
Thanks 🤙
@marktaylor71622 жыл бұрын
Yes, more rust FP vids, please.
@madhavan_raja2 жыл бұрын
6:14 why did you use .ok()? Instead of just the ?
@gt32932 жыл бұрын
Because the ? operator on a result requires the containing function to return a result, I believe. Ok() converts it into an option, which is what this function returns.
@madhavan_raja2 жыл бұрын
@@gt3293 According to the docs, parse() returns a Result. Why do we need to convert it into an option though? Aren't we getting a Result here already? Apologies if I am missing/misunderstanding something.
@gt32932 жыл бұрын
@@madhavan_raja The issue is that we can't use the Result. We need an Option (since that is what that closure returns). The .ok() method converts it so that we don't get a type error.
@madhavan_raja2 жыл бұрын
@@gt3293 Ah I see. Totally forgot to consider the fact that it was inside a closure. Thank you!
@edelsmurf2 жыл бұрын
Useful content, but, no, the combinator variation doesn’t seem more readable to me.
@FreeTheUyghurs2 жыл бұрын
Being the iterating happens only once collect() is called, does each combinator add an additional iteration over the vec or is it equivalent to one for loop?
@KohuGaly2 жыл бұрын
It's just one loop. Iterators are lazy. They are basically just structs with .next method in them. For example .map method returns a Map struct. The struct has two fields 1. the inner iterator struct, 2. the closure. The .next method basically looks like this: fn next(&mut self) { if let Some(value) = self.inner_iterator.next() { //calls next on the inner iterator Some( (self.closure)(value) ) //maps the value, by passing it to the closure } else { None } }
@SyamaMishra2 жыл бұрын
Is using unwrap after is_ok like this considered idiomatic rust or a code smell?
@piaIy2 жыл бұрын
I'm new to Rust but I think using if let would be the idiomatic way in this case.
@scotty30242 жыл бұрын
It's code smell, you are better off using a match statement in which the None or Result variant returns from the scope, ( the ? operator that he used does exactly that but shorter )
@jobosan48552 жыл бұрын
FP > OOP
@max_ishere Жыл бұрын
3:08 `cargo clippy`: Unnecessary unwrap, use if let Some(_) = name
@ClearerThanMud2 жыл бұрын
LOL -- The captions around @7:20 have Bogdan say "all the nun variants." I'm not Catholic; how many kinds of nuns are there?
@alexandersemionov57902 жыл бұрын
That’s some JavaScript stuff I like but in rust. TrustyScript :)
@31redorange082 жыл бұрын
That's not JS stuff. JS doesn't have an equivalent in its standard library.
@kevinbatdorf2 жыл бұрын
imperative vs declarative programming.
@Codeaholic12 жыл бұрын
filter_map!
@_Redu Жыл бұрын
Use of this example for the purpose of demonstrating the combinators is fine however in this particular case your approach is naive and inefficient. You don't need to map the ones with GPA < 3.5. It would be best done with a single pass of `fold` instead of `map` and `filter`.
@dangducthangg10132 жыл бұрын
hacked host info
@bernardoborges859813 күн бұрын
Broo
@porky11182 жыл бұрын
Seeing this code is pain :P
@flogginga_dead_horse40222 жыл бұрын
Be nicer to Wallace!!! lol
@letsgetrusty2 жыл бұрын
¯\_(ツ)_/¯
@JayGodseOnPlus2 жыл бұрын
In Ruby it would be something like : students.map{|s| s.split(' ')}.map{|t| {student: t[0], gpa: t[1].to_f}}.select{|u| u[gpa] >=3.5} I like that Rust's syntax for closures lends itself for easy chaining of combinators, just like Ruby's syntax does. (I believe that one of the core committers of Rust is a Ruby developer too). This is one reason I prefer Rust or Ruby over Go and Python.
@KohuGaly2 жыл бұрын
I was also very pleasantly surprised by the iterator combinators and their similarity to Ruby. Honestly, I did not know it was possible to have them in such a low-level language. Especially with zero overhead.