Zoran Horvat
Zoran Horvat
  • 161
  • 1 265 453
You’ll Never Write Functional C# Code if You Don’t Know This
First-class functions, among other things, means you can apply a function to a function to obtain a function. Did you get it?
C# supports first-class functions, but not always in the most obvious ways. This video will put your understanding of first-class functions to a test. If you can decipher it, you can progress to learn more about functional design in C#. Otherwise, the best course of action is probably to stop and try to understand this critical concept. It is up to you.
Download source code ► www.patreon.com/zoranhorvat
Join Discord server with topics on C# ► codinghelmet.com/go/discord
Enroll course *Beginning Object-Oriented Programming with C#* ► codinghelmet.com/go/beginning-oop-with-csharp
Subscribe ► czcams.com/channels/xsWfh8LCcn55mFB6zGBT1g.html
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
👨 About Me 👨
Hi, I’m Zoran, I have more than 20 years of experience as a software developer, architect, team lead, and more. I have been programming in C# since its inception in the early 2000s. Since 2017, I have started publishing professional video courses at Pluralsight and Udemy, and by this point, there are over 100 hours of the highest-quality videos you can watch on those platforms. On my CZcams channel, you can find shorter video forms focused on clarifying practical issues in coding, design, and architecture of .NET applications.❤️
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⚡️COPYRIGHT NOTICE:
The Copyright Laws of the United States recognize a “fair use” of copyrighted content. Section 107 of the U.S. Copyright Act states: “Notwithstanding the provisions of sections 106 and 106A, the fair use of a copyrighted work, including such use by reproduction in copies or phono records or by any other means specified by that section, for purposes such as criticism, comment, news reporting, teaching (including multiple copies for classroom use), scholarship, or research, is not an infringement of copyright." This video and our CZcams channel, in general, may contain certain copyrighted works that were not specifically authorized to be used by the copyright holder(s) but which we believe in good faith are protected by federal law and the Fair use doctrine for one or more of the reasons noted above.
#csharp #dotnet #functionalprogramming
zhlédnutí: 6 305

Video

Have You Ever Signaled async/await Progress in These Three Ways?
zhlédnutí 8KPřed dnem
Tasks have greatly simplified synchronization and data marshaling, which we can use quite effectively to transfer progress information back from the running task. There is always a ton of synchronization code at the back, but we shall never have to write that code. That is the beauty of working with .NET tasks. But the story does not end at the basic scenario. Have you ever thought of what data...
Master the Design of Functional Types in C#
zhlédnutí 10KPřed 21 dnem
Check out Dometrain and use code ZORAN for 15% off any course ► dometrain.com/?coupon_code=ZORAN The 1980s are over. The new C# does not work well with old habits. Get rid of them and dive into modern-day programming. The road to learning begins with understanding why C# becomes progressively more functional with every new version. Yet, most C# programmers do not know what is functional there o...
Clean Code Tip: Avoid Deep Nesting
zhlédnutí 6KPřed 28 dny
Clean Code Tip: Avoid Deep Nesting
Deep Dive on Locks & Deadlocks for Application Developers
zhlédnutí 5KPřed měsícem
Deep Dive on Locks & Deadlocks for Application Developers
How Do You Cancel an async Method? | Step-by-Step Tutorial
zhlédnutí 6KPřed měsícem
How Do You Cancel an async Method? | Step-by-Step Tutorial
C#, Dapper & SQL: Interview Questions With Answers
zhlédnutí 4,1KPřed měsícem
C#, Dapper & SQL: Interview Questions With Answers
When and How To Apply CQRS in an ASP.NET Core Application With EF Core
zhlédnutí 6KPřed měsícem
When and How To Apply CQRS in an ASP.NET Core Application With EF Core
The Secret of Unit Testing I Learned by Failing
zhlédnutí 3,8KPřed měsícem
The Secret of Unit Testing I Learned by Failing
How to Implement Strongly Typed IDs with EF Core and ASP.NET Core Razor Pages
zhlédnutí 4,5KPřed měsícem
How to Implement Strongly Typed IDs with EF Core and ASP.NET Core Razor Pages
Enjoy Strongly Typed Code Again With Covariant Return Types
zhlédnutí 6KPřed 2 měsíci
Enjoy Strongly Typed Code Again With Covariant Return Types
Master The L in SOLID
zhlédnutí 6KPřed 2 měsíci
Master The L in SOLID
Unveil the Mystery of the Liskov Substitution Principle
zhlédnutí 6KPřed 2 měsíci
Unveil the Mystery of the Liskov Substitution Principle
Learn C#: Method Hiding (and Why You Will Want To Avoid It)
zhlédnutí 4,2KPřed 2 měsíci
Learn C#: Method Hiding (and Why You Will Want To Avoid It)
Validating Records in C#: Everything You Ever Wanted To Know but Had No One To Ask
zhlédnutí 7KPřed 2 měsíci
Validating Records in C#: Everything You Ever Wanted To Know but Had No One To Ask
Learn C#: How Do Virtual Methods Work?
zhlédnutí 5KPřed 2 měsíci
Learn C#: How Do Virtual Methods Work?
The Lesson About GUID IDs I Learned the Hard Way
zhlédnutí 27KPřed 2 měsíci
The Lesson About GUID IDs I Learned the Hard Way
Learn C#: Abstract or Virtual Method, Which Fits Better Here?
zhlédnutí 9KPřed 3 měsíci
Learn C#: Abstract or Virtual Method, Which Fits Better Here?
This Is How Domain-Driven Design Makes Object-Oriented Design More Powerful
zhlédnutí 9KPřed 3 měsíci
This Is How Domain-Driven Design Makes Object-Oriented Design More Powerful
Avoid This Common Mistake in DDD Modeling
zhlédnutí 8KPřed 3 měsíci
Avoid This Common Mistake in DDD Modeling
Learn To Love DDD-Style Strongly Typed IDs
zhlédnutí 22KPřed 3 měsíci
Learn To Love DDD-Style Strongly Typed IDs
Let C# Tuples Become Your Best Friends
zhlédnutí 8KPřed 3 měsíci
Let C# Tuples Become Your Best Friends
The Ultimate Guide to C# Records
zhlédnutí 13KPřed 4 měsíci
The Ultimate Guide to C# Records
Here is How Fast is LINQ, Spans, and Everything
zhlédnutí 10KPřed 4 měsíci
Here is How Fast is LINQ, Spans, and Everything
This Is the Place for LINQ in Modern .NET Design
zhlédnutí 9KPřed 4 měsíci
This Is the Place for LINQ in Modern .NET Design
17 Pieces of C# Syntax That Make Your Code Short
zhlédnutí 17KPřed 4 měsíci
17 Pieces of C# Syntax That Make Your Code Short
3 Shocking Misconceptions Among C# Programmers
zhlédnutí 13KPřed 4 měsíci
3 Shocking Misconceptions Among C# Programmers
Will All My Classes Look Like Records Now?
zhlédnutí 6KPřed 5 měsíci
Will All My Classes Look Like Records Now?
Why is C# Evolving This Way?
zhlédnutí 20KPřed 5 měsíci
Why is C# Evolving This Way?
Getting Started With Azure Storage | Tutorial
zhlédnutí 3,8KPřed 5 měsíci
Getting Started With Azure Storage | Tutorial

Komentáře

  • @louisfrancisco2171
    @louisfrancisco2171 Před 10 hodinami

    This simple type does NOT promises to contain a non-empty string.

  • @user-ji6ip7ou8d
    @user-ji6ip7ou8d Před 2 dny

    Looks overcomplicating. Couldn't you just create another method that sorts in the descending order? books.SortByDescending(...) or books.Sort(..., descending: true)

    • @zoran-horvat
      @zoran-horvat Před 2 dny

      The List class is from BCL. I cannot create any methods in it.

  • @user-ji6ip7ou8d
    @user-ji6ip7ou8d Před 2 dny

    I don't understand how yield works, can you explain?

  • @djp_video
    @djp_video Před 2 dny

    I still don't understand the paranoia and aversion to nulls. They are incredibly useful, and not that hard to work with!

    • @zoran-horvat
      @zoran-horvat Před 2 dny

      They are not incredibly useful. Start from that point.

    • @djp_video
      @djp_video Před 2 dny

      ​@@zoran-horvat I beg to differ. For years I worked in languages that didn't support them, so we had to use sentinel or magic values to determine when data is not available or otherwise hasn't been set yet. That's a much bigger nightmare. Moving to tools which added null functionality improved that drastically! The concept of a null is so powerful!!! And made working with data and ensuring that I'm working with the right data so much easier! And the concept isn't even hard to grasp. One example... you have a method to query a database for user by ID... and go to retrieve user 123, but user ID 123 doesn't exist in the database, for whatever reason. Having that method intentionally return a null tells the calling code that there is no user 123; it doesn't exist. The other techniques I see used, either to throw an exception, or instantiate a blank "fake" user to avoid the null are both terrible ideas -- exceptions are slow and are intended to be "exceptional" when unpredictable things happen, and creating a blank object... well, you're working with data that isn't real and the calling code has to check for that too. Result<> objects don't solve this problem, because the database query actually is successful -- there is just no result that matches the specified criteria. A simple null return makes it all very easy without wasting any resources. And the Optional<> technique introduces a lot of extra boilerplate code that just isn't necessary. Most of the time when I see developers struggling with null exceptions, it's because they are trying to process data that they haven't initialized yet. So that exception is incredibly useful! It tells them that, hey, you forgot to do something somewhere else in your code. The current C# nullable reference type behavior encourages the practice of new()ing objects just to make the warnings go away or letting C# instantiate default objects for you that don't represent real data... so the code that would have thrown an exception using the "old" way if nulls were embraced, no longer throws those exceptions. So while, yes, it avoids the exception, that code is now working with fake data, and because no error is thrown, the developer isn't made aware of it. It happily proceeds down the happy path as if everything is perfect when it really isn't. This is a bigger problem than just fixing the exception. Exceptions tell you that you did something wrong and it needs to be addressed. But with the other technique, the code isn't even aware that there is a problem. When you do discover it, you have to backtrace to see where your object reference was assigned incorrectly. Very frustrating and time consuming. I'll take an exception over that every time. Many techniques for avoid nulls also abstract away the concept that reference-type objects are actually pointers and memory has to be allocated and CPU cycles are used to create that an object any time you instantiate or even declare one that isn't nullable. It makes developers much more careless about using those resources. And causes a lot of confusion about how reference types actually work. The majority of developers that I know that actually like C#'s nullable reference feature, I promise you, don't understand how objects actually work, and that modifying the contents of an object passed to a method actually modify the original object. The whole concept (and benefits) of reference objects is lost on them. And I believe that leads to more bugs than just taking the time to learn to work with nulls in the first place. I'd even go so far to say that anyone who doesn't like nulls, or doesn't understand nulls, shouldn't be using reference types at all, because if a null seems like an inconvenience, they don't get why objects can be so useful and so powerful. Structs are probably better for developers at that skill level. Techniques like what you show in this video make it much more difficult to determine whether you have required data missing, or if the data is actually an empty value. There is a big difference between the two, and hiding that for the sake of avoiding a few null checks and useful exceptions is kind of sad. Because of the null coalescing and the null conditional operator, dealing with nulls is really easy. The stuff you're doing in this and other videos is a lot more work than just learning how to use nulls properly in the first place. The code is longer, more complicated, and harder to read than anything I write which fully embraces the concept of a null.

  • @Wil_Bloodworth
    @Wil_Bloodworth Před 2 dny

    You might want to read the Liskov Substitution Principle again as it only applies to derived/child classes not just any general substitution. Span<T> does not inherit/derive from List<T> so this has nothing to do with the LSP principle and you're not violating LSP with your example. Maybe Barbara watches your channel and she can comment. LOL

    • @zoran-horvat
      @zoran-horvat Před 2 dny

      LSP is not about classes but about types. So much about who should read the principle again. Regarding my video, I am not sure which timestamp in the video you are referring to. Before clarifying, be aware that assigning a list to a span without recreating the object makes the list a subtype of a span, quite formally. It is the same effect as what you would accomplish by defining a custom implicit cast operator without a direct subclass relationship. Any cast operation defines a subtype relationship, and implicit cast does that with full formality. Now with a lowered cynicism on your side and more seriousness, I would like to hear which timestamp in the video should cause concern.

  • @conundrum2u
    @conundrum2u Před 3 dny

    Liskov's states simply that the substitution should not break semantical behavior of the underlying base class's implementation. If a new exception type is a derivation of an exception type that the parent can throw, it's entirely acceptable for a derivation to throw a new exception. You also don't mention covariance or contravariance with respect to parameters and return types.

    • @zoran-horvat
      @zoran-horvat Před 3 dny

      The base class does not throw. Both classes are non-generic and therefore invariant.

  • @IcaroFelix2023
    @IcaroFelix2023 Před 3 dny

    Are you using some kind of library of functional extensions to CSharp ? If yes, could you say which is it ?

    • @zoran-horvat
      @zoran-horvat Před 2 dny

      Sometimes I use LanguageExt, mostly for Option and Result definitions. I regularly depend on language syntax alone, rather than third party libraries, because that is the only way I can preserve backward compatibility in the long run.

  • @ucretsiztakipci6612

    decorator design pattern

  • @makemeafirewall
    @makemeafirewall Před 3 dny

    It shows that you are a real professional

  • @lettuceturnipthebeets790

    is this decorator pattern all over again? 😅

  • @pmcgee003
    @pmcgee003 Před 3 dny

    Is it the "Why is C# Evolving This WAY" full video that discusses the elevation of functions like this? czcams.com/video/RfEbn9aXY-Y/video.html

    • @zoran-horvat
      @zoran-horvat Před 3 dny

      That video is explaining the evolution of the C# syntax over the last 15 years. That video is not dedicated specifically to elevates types, but it includes many topics and a mention of some of the types from this short video, all put in the perspective of modern programming in C#.

    • @pmcgee003
      @pmcgee003 Před 3 dny

      I very much like your channel. Lots of good FP information. I don't use C#, but I still like the information and the view to language progression.

  • @ucretsiztakipci6612

    Is it true that works like singleton pattern?

  • @Endomorphism
    @Endomorphism Před 3 dny

    Oop create whole class,where in fp we just need a function 😂 In fp it’s called function composition the first and most probably only one you need

  • @treeplate512
    @treeplate512 Před 3 dny

    wait why is the comparer a class? can't it just be a function?

    • @zoran-horvat
      @zoran-horvat Před 3 dny

      It can be the function (Comparison delegate), and that was the last line added in the demo. It is common in .NET to include an overload, so to accept both the IComparer and Comparison, to suit every caller. Java supports that natively, as you can assign a lambda to an interface variable, but in .NET we still have to write both methods.

  • @pirati02
    @pirati02 Před 3 dny

    Adapter?

    • @zoran-horvat
      @zoran-horvat Před 3 dny

      Adapter would have to change the type, i.e. adapt one type to another.

  • @conundrum2u
    @conundrum2u Před 3 dny

    there's no need for greater than or equals evaluations, if they're all equal it doesn't matter which number you choose, so you only need to evaluate if one is greater. you're going to need to evaluate them all, so creating overloads that handle a variable number of arguments is a superset or collection level method that should operate on a 2 argument method. it's not a functional approach, it's a separation of concerns style of coding where you're applying concepts of composability. you're basically re-implementing IComparable and Reduce. your approach should always be start with the specific and then work towards the generic. this applies for functional and OOP

    • @zoran-horvat
      @zoran-horvat Před 3 dny

      Greater or equal is common in programming because it preserves order. Greater than reverses the order. It is relevant when the algorithm applies to reference types. Why have one algorithm for ints and a different one for references if both do the same thing? Applying a two-argument function to N arguments is the functional fold operator.

    • @conundrum2u
      @conundrum2u Před 3 dny

      I'm using your example in the video. Using a function or a series of functions does not mean that you're coding in a functional style. All logic in both styles happens in functions. Functional means no mutations on an original data structure and no side effects. All examples you've given are technically functional approaches. In the example you've given, order has no meaning and no consequence. You're evaluating 2 sides at one time. 1 Always wins. They're value types. Your question for value and reference types, I already answered with IComparable. Any type, value or reference, that implements IComparable can be used by the existing library functions that use the interface. This is why I said write for the specific and move towards the generic. The fold function is also known as reduce, which is why I said Reduce.

  • @cesarpinto3276
    @cesarpinto3276 Před 4 dny

    Yep, have used this in a websockets app I've built for fun. Not exactly critical for an app with no users haha but still a good learning experience building it as if it were! Maybe a complimentary idea for a short could be Span<T> and Memory<T> vs the older way using arrays

  • @chrisauret3785
    @chrisauret3785 Před 4 dny

    The white background made me blind

  • @pharoah327
    @pharoah327 Před 5 dny

    Won't this cause us to always check each moving ability to see which is null and which isn't? Every time I want to do something with a vehicle object, I'll have spaghetti code if statements checking to see which ability it has that's not null. Don't get me wrong, this solution clearly has benefits over inheritance but let's be clear about the drawbacks too.

  • @FunWithBits
    @FunWithBits Před 5 dny

    nice... I use c# all the time and did not know this and wish it had this. Now we just need a myValue.ClampToZero() extension. (myValue < 0 ? 0 : myValue) This is instead of Math.Max(0, MyValue).

  • @0XAN
    @0XAN Před 5 dny

    i'm afraid C# is becoming a language for wankers

  • @okcharles7
    @okcharles7 Před 5 dny

    This time, the Turkish Ice cream man flips too long for the C#hildren to take the F#luffy.

  • @user-xc8wv5mz5u
    @user-xc8wv5mz5u Před 5 dny

    (Native speaker is Chinese, the following is from machine translation) Suddenly I realized that using static actually breaks the boundary between object-oriented programming languages and functional programming languages.

  • @ayoubrayanemesbah8845

    Lean

  • @creepy99
    @creepy99 Před 5 dny

    Code is, on average, written once and read 10x. Write your code to be easily read and understood. If I have to do mental olympics to read and understand your code, it's probably too condensed. Shorter != better.

    • @zoran-horvat
      @zoran-horvat Před 5 dny

      Which line of code is that?

    • @creepy99
      @creepy99 Před 5 dny

      @@zoran-horvat Sorry... I was not talking directly to you. I meant the general "you", as in the person that wrote whatever code I'm reading. I prefer the first line in the Car example because it's clearer (to me). I don't have to think or look something up, it's just clear from the start. Hope that clears things up... sorry for the confusion.

  • @F2H16
    @F2H16 Před 5 dny

    Amazing! You are an articulate person, it would be nice to get a DDD course (An affordable one) from you. It would have covered your programming mastery and eloquence to deliver the goods.

  • @m31coding
    @m31coding Před 5 dny

    Thank you very much for this great video! The advantages of fluent interfaces become very clear. However, for complex use cases, writing a fluent interface can become tedious. To address this, you might find the M31.FluentAPI source generator library I created helpful. Happy coding!

  • @dusanknezevic9072
    @dusanknezevic9072 Před 6 dny

    Well. It's awesome that you can do this. Convolutedness of signatures is a bit of a problem. All delegate types are incompatible with one another even if they have the same signature (seen as different types by compiler). You can get around this by explicitly typing (wrapping) one. Prime example is that you can't assign Func<A, bool> to Predicate<A> and vice versa. It's gonna be interesting to see how C# tackles these incoveniences. Functional first languages win here. Like Haskell or F#.

    • @zoran-horvat
      @zoran-horvat Před 5 dny

      Incompatibility of delegates is not an inconvenience - it is intentional. The same situation is with classes. Their objects are not assignable to each other even when the two classes have the same shape.

    • @dusanknezevic9072
      @dusanknezevic9072 Před 4 dny

      @zoran-horvat That's more or less ok, depending on point of view. There have been quite interesting discussions with C# team about this, but that's another point Unreadability of type signatures is quite a problem. As is currying. It's quite hard to do it in functional way. If I wanted functions to be partially applied that's where type signature unreadability gets problematic. Discriminated unions and exhaustive pattern matching would be great additions to C#. But I fear that may drive C# into F# territory with some bad trade-offs in readability and semantics to keep backwards compatibility.

  • @Myself0094
    @Myself0094 Před 6 dny

    In whole honesty this is exactly where functional C# loses to regular F# and where it becomes obvious it’s not functional first. It sure can be functional enough, but should it?

  • @Rein______
    @Rein______ Před 6 dny

    Do this at work just to troll everybody. You dont understand it? Your problem. Lol!

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      That is what makes it a good joke, I guess.

  • @Curlack
    @Curlack Před 6 dny

    To return items from primary of alternate if primary contains nothing. Couldn't we also use two foreach loops where first will set found boolean and afterwards return if found?

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      Some sequences throw when you try to iterate them twice. For example, streams do not support multiple iterations in general, and so a sequence deserialized from a stream would throw.

    • @Curlack
      @Curlack Před 6 dny

      @@zoran-horvat was thinking more in the lines of the following code (see found variable): public IEnumerable<DiscountApplication> GetDiscountAmounts(Money price, DiscountContext context) { var found = false; foreach (var discount in _primary.GetDiscountAmounts(price, context)) { found = true; yield return discount; } if (found) yield break; foreach (var discount in _alternate.GetDiscountAmounts(price, context)) { yield return discount; } }

  • @LordErnie
    @LordErnie Před 6 dny

    I agree with your description of functional programming. I agree to most of what you do. But there is one slight problem. Functions aren't first class citizens in C# as far as I know. Functions cannot exist on their own. They must exist on a class. A delegate is basically a type description for a function. Its header becomes its type in a sense, because it is. But a description is not a concrete instance. Those must live in the form of methods on objects. Even static methods are just tricks, they are still part of a class. A first class function can live on its own. That means no classes. It can be created, defined, all without a class, or a type, it just exists. Static methods are just a trick (in a sense, they do have use in an OO context these days within C#). Delegates are indeed WAY nicer then only using Func and Action! I agree. Makes it look more like Haskell, where every function needs an abstract type definition (not called that, but we get the idea).

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      Delegate types exist outside enclosing classes, and they are functions.

  • @DmitriNesteruk
    @DmitriNesteruk Před 6 dny

    Why have ToOption() when you can just have an implicit conversion operator from T to Option<T>? That way you can transparently declare parameters of type Option<T> and pass ordinary objects into them. Also, why not have `public static Option<T> None = new();` as a single instance? There is no real need to have it as a method. In fact, you could sacrifice type information and introduce a non-generic (Value)Option<T> just to have a `None` member so it could be referred to without extra type information.

  • @DmitriNesteruk
    @DmitriNesteruk Před 6 dny

    The use of terminology here is not 100% correct, because normally `Reduce()` does a completely different thing. The correct term here would be something like `Otherwise()` or something to that effect. `Map()` is more correct though you could equally call it `Select()` (per LINQ terminology), `Take()` or something else. Also, in `GetLabel()`, the initial call to `person.` can throw if it's null, and this call isn't handled here by the Maybe monad.

  • @7th_CAV_Trooper
    @7th_CAV_Trooper Před 6 dny

    I'm going to have to watch this a few times. My OO ordered brain resists the truth. :)

    • @1992jamo
      @1992jamo Před 6 dny

      Functional programming can be excellent, but this is unreadable. The delegates hide the structure of the actual functions and when it's this nested it's a nightmare. Without putting words in Zoran's mouth, I think that he's showing the power of containing state within expressions rather than classes. But going between 5 layers of functions and their abstract representations as delegates seems a bit much to me when we're literally just filtering a collection.

  • @websystema
    @websystema Před 6 dny

    Thanks for the video

  • @prakashKumar-zj8nw
    @prakashKumar-zj8nw Před 6 dny

    This type of expert level coding gives me orgasm😂

  • @10199able
    @10199able Před 6 dny

    mind blown!

  • @XXnickles
    @XXnickles Před 6 dny

    You just showcased one of the main barriers I have had with functional paradigms in c#: the complexity in the signatures. Whether we like it or not, c# is not designed for this, and this is a real pain in the rear end specifically when you work on a team and people have a hard time following (heck, I have tough times myself!) With that said, that trick with the delegate definition is a good one that I am taking note of it. What a shame that currying has to be this complicated (in terms of readability) as it is one of those functional tools that can be very handy in several scenarios to remove a bunch of interfaces and abstract clases. Great explanation!

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      C# will hardly advance further in readability, unfortunately.

    •  Před 6 dny

      Viewability and listenability are the future, so don't care.

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      I like the way you formulated it.

  • @1992jamo
    @1992jamo Před 6 dny

    So we're using FilterBooks to return a delegate of type Filter<BookType> which is extended by the static extension method "for", which takes a function that returns Task<IEnumerable<Books>>, and returns a function that has a search string parameter, and then this function is passed to the PromptAndReport method which matches the FilteredDataSource<BookType> delegate? Then finally, it pass it a string to do the filtering? My God.

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      That's it :) Now, the reason! The reason is that one function knows the data source and another function knows the phrase. Neither should depend on other's data, so the delegate arithmetic comes to the picture. It is the direct inverse of traditional dependency injection in OOP.

    • @1992jamo
      @1992jamo Před 5 dny

      @@zoran-horvat I have to admit Zoran, it took me longer than I care to admit to work out what I was seeing. Clearly you are a very talented and experienced developer, but the delegates hide so much that it's extremely hard for me to read without seeing their definitions. As always, thanks for the video as I have learned lots. I didn't even realise that functions could be extended. It's also very interesting to see how state can be entirely contained within functions.

    • @zoran-horvat
      @zoran-horvat Před 5 dny

      @@1992jamo I told you it is going to be difficult :) But those things you have seen in the end, that is the important lesson. Give it some time, and you will see that it will change the way you look at the functions and delegates, not only in C# but in any language.

  • @Naton
    @Naton Před 6 dny

    as much as i like FP, i worry my juniors wont be able to understand my convoluted delegates

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      True, they won't. It takes a lot of experience and even more formal knowledge to start to appreciate functional designs.

    • @Robert-yw5ms
      @Robert-yw5ms Před 6 dny

      I had a senior recently not understand the curried function I'd written. That one surprised me.

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      @@Robert-yw5ms Currying requires a wider view on functions to understand. A litmus test is for someone to answer why F# functions have no parentheses around arguments.

    • @UwuseSawase
      @UwuseSawase Před 6 dny

      ​@@zoran-horvat Do i have to know the mathematical background also, to get very good at funktional programming?

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      @@UwuseSawase You should have a clear understanding of mappings and functions. That is primarily algebra, rather than mathematical analysis, for example.

  • @1lem0nati0n5
    @1lem0nati0n5 Před 6 dny

    Program.cs line 10 is dataSource a great name for the argument?

  • @danilodjokic5303
    @danilodjokic5303 Před 6 dny

    Great video, really puts into perspective how C# has been evolving over the years. How often do you get to write this type of code in production? Do you find it confuses people that are accustomed to the traditional OOP way of doing things, how do you get over that? Pozdrav iz Finsoft/Fincore-a !

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      This is the regular coding pattern when designing pure functional code. It is not common to see this kind of code mixed together with OOP design.

  • @martinprohn2433
    @martinprohn2433 Před 6 dny

    Well thanks for the video. My personal opinion is, that I would have stopped before the introduction of "OrElse". I find the "FirstOf()" outer call clearer, because all three calls inside are on the same level. With OrElse on the other hand, the first call is outside the OrElse method call, but the other two inside OrElse. I find that ugly. But that’s probably just my opinion. For the same reason I prefer "Enumerable.Zip(a,b,…)" instead of "a.Zip(b, …)". (Usually with line breaks between the parameters.)

  • @Joanarkj
    @Joanarkj Před 6 dny

    I understood nothing. 😢

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      Watch again. This is literally the single point you should understand, and once you do...

    • @abj136
      @abj136 Před 6 dny

      @@zoran-horvat There’s many C# features used here that I’m not familiar with. What means “b!”? What do delegates do in this context? Also I constantly lost track of definitions and had to scrub back and forth through the video to get what you were referencing. And the final point of difficulty is not understanding WHY all this indirection would exist. I can do this same function without all these.

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      @@abj136 Can you?

    • @David-id6jw
      @David-id6jw Před 6 dny

      @@abj136 The "b!" is easy enough to explain. "!" is the null forgiving operator. If you're using nullable reference types, you use "?" to designate that a variable or return type can be null. His Create() functions return things like "BookType?" (this was shown in a recent video he did - Master the Design of Functional Types in C#). So his "a" and "b" variables could potentially be null if the creation logic failed. However, since this is a demo, he knows that those are not going to be null, and doesn't want warning squiggles distracting from what he's talking about. So he uses the "!" operator to say, "I definitely know that these are not null, even if the analysis logic says they might be, so don't show me any warnings about them." Basically, they're not related to the topic he's trying to explain, just part of the general C# syntax.

  • @YordanTGeorgiev
    @YordanTGeorgiev Před 6 dny

    I really try to understand your videos, but for some reason most of them are not clear at all😶

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      This particular detail is hard. But once you clarify it, you'll be looking at functions in an entirely new way!

    • @colcoomagnumar
      @colcoomagnumar Před 6 dny

      Me too. But I love Zoran’s presentation style and I keep repeating videos until things start to click. I don’t converse like this with my fellow developers so I’m just a bit rusty and Zoran sets an excellent standard to rise to.

    • @d2pgoon86
      @d2pgoon86 Před 6 dny

      There are a couple reasons for this: 1. He moves quickly in his demos. I ⏸️ and ⏪ all the time to clarify details that he might gloss over. I prefer this now as I don't need to sit thru mind numbing tedious explanations. 2. He focuses strictly on the topic, so if something he does is unclear (say with the bare Func signatures), it's mostly on you to figure it out. 3. He's now skipping over refactorings like Func -> BookFilter etc., because that's now understandably hidden behind Patreon. I've come to love Zoran's style as he speaks to you like a young child but does not treat you as one--you must come prepared with knowledge of c#, because he focuses on the abstractions which is where the real learning happens. Just keep watching and it'll click!

    • @1992jamo
      @1992jamo Před 6 dny

      @@d2pgoon86 I think point 3 is the most important. Especially since the delegates hide parameters.

    • @chrisspire
      @chrisspire Před 5 dny

      I am a beginner developer (well, I did that 20 years ago as a hobby in school) and I went through Zoran's tutorials on Udemy to refresh and update my knowledge. They were phenomenal and easy to understand. Most of the stuff here on YT is too advanced for me but I could not find better source of C# knowledge on the internet than Zoran!

  • @Robert-yw5ms
    @Robert-yw5ms Před 6 dny

    The main use case I've found for currying has actually been in UI logic. I.e. you have some inputs that should trigger redraws of other parts of the UI along with some other custom actions? Tedious without currying, simple with currying.

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      That makes sense. Currying is closely related to dependency injection, in the sense that it applies to scenarios where one party provides dependencies and other party provides parameters.

    •  Před 6 dny

      My practical experience says me to not care about UI LOGIC so much. UIs are rewritten each 5 years.

  • @shadowsir
    @shadowsir Před 6 dny

    You have to admit F# reads a heck of a lot easier than whatever this C# "we must define everything" mess is... 😅

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      It is not a mess, but yes, F# syntax is streamlined.

    • @Robert-yw5ms
      @Robert-yw5ms Před 6 dny

      I've barely dabbled with f#, so this is a genuine question: is the type inference really powerful enough to work out what all the types here would be without being told?

    • @zoran-horvat
      @zoran-horvat Před 6 dny

      @@Robert-yw5ms Almost always yes, but the implementation of the compiler must change. The type resolution might sometimes need to wait until the time it is used. In the meanwhile, the compiler might go along with rough guesses. As a last resort, F# settles down with a guess, such as always assuming some numeric type is int unless proven otherwise. I am not the best source for questions regarding the F# compilation process, I must say that, too.

    • @shadowsir
      @shadowsir Před 6 dny

      @@Robert-yw5ms Hmm, in this case, you'd probably want to define the input types. let filter (dataSource: Async<BookType seq>) (phrase: string) = async { let! bookTypes = dataSource return bookTypes |> Seq.filter (fun bookType -> bookType.Title.Contains(phrase, StringComparison.InvariantCultureIgnoreCase)) } The return type would just be deduced, no need to specify it. We usually create a function to be able to "map" an Async, so without the computation expression: let filter (dataSource: Async<BookType seq>) (phrase: string) = dataSource |> Async.map (Seq.filter (fun bookType -> bookType.Title.Contains(phrase, StringComparison.InvariantCultureIgnoreCase))

  • @MehediHasan-xd6rj
    @MehediHasan-xd6rj Před 7 dny

    Please take 1000 likes and thanks from me for your excellent Job. I am following you from the Pluralsight course. I have become a fan of your CZcams videos.

  • @shauas4224
    @shauas4224 Před 7 dny

    I use this very often in unity