Good explanation. The original function summed the two arrays up to n being the length of the shorter array. Do the refactored functions also do that or will the cover every element of the longest array?
I liked your down to earth approach on this subtle "implementation details". The dissappear of branching is the magic of abstraction in action: Option carries (abstracts) the computational context of the possibility of failure, so the implementation can focus on the intended manipulations. I come from a Haskell background and got to follow along just right; there Maybe, the equivalent of Option, is in the core libraries as is considered idiomatic. I guess some programmers might see this approach pretty ad-hoc or a case of "killing ants with canons", but the re-usability of this pattern (Monad) make this approach quite useful. Great video.
It's sad that you stopped. You gave up due to slow growth? It kills one's motivation, for sure. However, I figured out a way to optimize the YT algo which gives you 500-2000 high quality views in a couple of days (and 30 subscribers per day). I will tell you how it's done if you make some more videos. JB
the previoud code wad much more readable. Also, you could have used guards to make the previous code even better. What you have below is just ridiculous, and probably performs much worse.
What I like about it the most is that: While it's an overkill for cases that TS narrowing handles, if narrowing doesn't work you're screwed. And using Options code that would be nearly impossible to type-check (e.g. getting TS to work would be so hacky you'd rather just assert) become possible to write somewhat elegantly
thanks a lot for your videos on fp-ts. just a humble video idea: In a front-end app, what about using fp-ts power to validate an import of a csv file via a form, and showing a meaningful error message to the end-user?
These videos are great. Being new to functional programming I wanted to make use of a full featured library such as fp-ts, but sadly the documentation is very light. This left me wondering what most of the modules do, or how I can use them. Your videos have really helped on giving me something to start from and explore from there. Not sure if you any plans for more in the future but they would be most welcome! *subscribed*
Maybe just a matter of preference, but the inner map/chain functions can be combined into chain/flow pattern. E.g. checkResource = flow(pickResource, getTld, O.map(tldIsCom) and just use checkResource in the chain method removing the maps
Interesting. I'm trying to wrap my head around it. But without having looked at the source code, I would say, O.Do simply is a shorthand for O.some({}). With bind being declared as bind: <T extends {}, N>(key: string, (t: T) => O.Option<N>) => (opt: Option<T>) => Option<T & {[key]: N}> If you think about it like this, this syntax is way less mistifying.
I am new to fp programming in typescript, but what's the point of doing all of this when you can just refactor the code that you showed at the start of the video like this: const isDotCom = (url: string): boolean => { try { const parts = parseUrl(url).resource.split(".") return parts.length > 1 ? parts.at(-1) === "com" : false } catch { return false } } Edit: makes sense now.
The thing is (and maybe I'm mistaken) that the first function does only one iteration, while the first refactor does the zip iteration, the map iteration and the reduce iteration. Which should be fine for small arrays but bad for larger data sets if performance is important to you. Besides that, I love the functional programming style.
Hey Ryan! Everything related to fp-ts in your channel is spectacular! I don't know why you don't upload new videos about it, but would be fantastic if you continue! Keep doing it, plz!
I'm a fan of FP myself but I gotta admit that the way the code was presented before the refactoring was way clearer and possibly faster as well. Sometimes imperative style just works better I guess.
This is a fantastic series. Actually approachable. I hope you make more :) I'd love to see an example of how to tie a flow with side effects (eg, logging or async whatever).
(Watching this video again 3 months later.) I wonder how hard it would be to justify this to a senior dev (I’m just 1,5 years into my career) if I wanted to use this in a TS codebase… Big question if this kind of Haskelly notation might actually be too obscure for a TS project. I mean, I imagine being someone coming in from lite a 3 month code boot camp, barely even understanding .map or Redux, and then all of the sudden seeing this. I would probably need to spend a few hours to get them to see what is even going on here, let alone explain what the benefit it. But maybe chainability and composability and reusability and type safety should be so core to the craft that they should be as mandatory to learn as if-statements and for loops…
Yeah, you're not alone in this dilemma. At one extreme, you reduce everything down to "bootcamp-level". At the other, you introduce levels of abstraction beyond comprehension. Either way, not much work gets done. There is a sweet spot that will vary between teams, projects, and codebases.
You’re a really good teacher by the way, showing progress and justification by working up from a non-optimal solution to a fp-better solution. (I know better here is in quotes as it is all subjective. But you know what I mean… 😄)
It's been intuitive to me for a long time that there had to be a way to write code that entirely avoids if statements. I've just never understood how to do it. Every time I've tried, I've ended up with these Frankenstein like structures that hardly seem worth the trouble and even worse, completely unreadable, in a way that would make me hate you with a passion if you were the next dev who had to manage that code base. This is the first video where I've seen it achieved in a way that both makes sense and it's clean. It's everything I knew i wanted but couldn't achieve. Thank you. I'm glad I stuck around for the magic trick at the end. To be honest, at the same time it was a bit of a slog.