17 Pieces of C# Syntax That Make Your Code Short

2024 ж. 12 Мам.
16 386 Рет қаралды

Become a sponsor to access source code ► / source-code-17-c-95476297
Join Discord server with topics on C# ► codinghelmet.com/go/discord
Enroll course Beginning Object-Oriented Programming with C# ► codinghelmet.com/go/beginning...
The syntax of the C# programming language is changing. It has been changing since version 1, and we are still witnessing the addition of more details to it. Have you ever considered why we are getting these pieces of syntax and not some other?
In this video, we will revisit a number of seemingly minor improvements added to the language over the years and draw them to a conclusion: Novel C# syntax makes writing pure functions easy.
It takes time to accept pure functions as a design tool and a lot of practice to make the most out of them. But one thing I promise to you: Once you get there, you will never look back to the old-school imperative coding.
And more: Your code will be way shorter than it used to be. How much shorter? 50-70% on average. That should motivate every programmer to start using the novel C# syntax as intended.
⚡️Chapters:
⌚ 00:00 Intro
⌚ 00:53 Imperative code (100% length)
⌚ 03:17 Object-oriented code (57% length)
⌚ 05:35 Comparing different styles
⌚ 06:45 Functional code (50% length)
⌚ 09:17 Pure functions (40% length)
⌚ 11:58 Conclusion
Thank you so much for watching! Please like, comment & share this video as it helps me a ton!! Don't forget to subscribe to my channel for more amazing videos and make sure to hit the bell icon to never miss any updates.🔥❤️
✅🔔 Become a patron ► / zoranhorvat
✅🔔 Subscribe ► / @zoran-horvat
⭐ Learn more from video courses:
Beginning Object-oriented Programming with C# ► codinghelmet.com/go/beginning...
⭐ Collections and Generics in C# ► codinghelmet.com/go/collectio...
⭐ Making Your C# Code More Object-oriented ► codinghelmet.com/go/making-yo...
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⚡️ Have a look at our other Videos :
👉 Using GitHub Copilot to Write Complex Code | Step-by-step Tutorial ► • Using GitHub Copilot t...
👉 Coding with GitHub Copilot - Beginner to Master | VS Code Demo ► • A Comprehensive Guide ...
👉 What is Covariance and Contravariance in C# ► • What is Covariance and...
How to Initialize a Clean ASP.NET Core Project with Entity Framework Core and Identity ► • How to Initialize a Cl...
👉 The Null Conundrum: A Guide to Optional Objects in C# ► • How to Avoid Null Refe...
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⭐ CONNECT WITH ME 📱👨
🌐Become a patron ► / zoranhorvat
🌐Buy me a Coffee ► ko-fi.com/zoranhorvat
🗳 Pluralsight Courses ► codinghelmet.com/go/pluralsight
📸 Udemy Courses ► codinghelmet.com/go/udemy
📸 Join me on Twitter ► / zoranh75
🌐 Read my Articles ► codinghelmet.com/articles
📸 Join me on LinkedIn ► / zoran-horvat
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
👨 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 KZhead channel, you can find shorter video forms focused on clarifying practical issues in coding, design, and architecture of .NET applications.❤️
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
⚡️RIGHT 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 KZhead 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

Пікірлер
  • I would argue that code readability is far more important than reducing the code by 3, 5, or even 10 lines. Not to mention, that the code should be easy to debug. It seems like a challenge to make the code as short as possible which might be suitable for Codewars, but not for production code. So I would use "syntax improvement" that are really syntax improvements - that will show the intent and keep code readable and easy to debug.

    @Eltin123456@Eltin1234564 ай бұрын
    • I agree, but then I would add that mapping expressions are also more readable than the imperative code. Let alone that they are reducing bug count by an order of magnitude.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • i agree, you are missing one point, the bonus way is also easily unit testable by very little and readable blocks

      @lordicemaniac@lordicemaniac4 ай бұрын
    • Readability and shortness do not oppose each other. Short codes are each to capture at one gaze; hence improving readability.

      @anm3037@anm30374 ай бұрын
    • @@lordicemaniac Expressions are easier to test than imperative blocks.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat that is what i said, at least tried to... that the last bonus form maybe looks harder to read at first, but it is much easier to make very easy to read unit tests

      @lordicemaniac@lordicemaniac4 ай бұрын
  • I adore all your lectures, including on Pluralsight. You have truly changed my programming style/vision/life and my code is 10x less buggy than it was 10 years ago! Zoran Guru of Functional Programming! IoC + Interfaces + Linq + SOLID + Functional Programming (no loops, no deep branches, no cyclomatic complexity, only Linq and self-described small methods) == Success. Thanks a lot!

    @AlexUkrop@AlexUkrop4 ай бұрын
  • I like how your videos summarize most of the features from any C# versions, especially the new ones. I've seen the "when" keyword before, but never understood its use until now, same for using switches to declare variables.

    @pixelguy2231@pixelguy22314 ай бұрын
    • Designers of C# are constantly watching what kind of code people write. Most of the additions to the language stem from practical needs and their net result is shorter code, i.e. the language saves us from repeatedly writing the same idioms.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat Interesting fact I see

      @pixelguy2231@pixelguy22314 ай бұрын
  • I watch your videos time to time, and I have to admit that each time I watch I appreciate more the content, because I understand the code and the use-cases where I would use these techniques. You're a great mentor, I've started learning from your videos in the beginning of my career, now I feel happy to have materialized that knowledge.

    @fisnikmaloku3425@fisnikmaloku34254 ай бұрын
  • As he says; F# is even more readable (preferable?). Here is a variant: let tryParse (input:string) = match System.Int32.TryParse input with | true, v -> Some v | _ -> None let produceSum (input:int seq) = match input |> Seq.toList with | [max; next; _] -> max + next | _ -> - 1 let sumGreatestTwo (input:string seq)= input |> Seq.choose tryParse |> Seq.sortDescending |> produceSum

    @oysteinhaga@oysteinhaga4 ай бұрын
    • That removes at least a half of keys required to type the same code.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • I like a lot your channel and your functional approach. I've been trying to do my code like this for years

    @luc9volts@luc9volts4 ай бұрын
  • Excellent content. I'm deadly curios about the performance between them.

    @ucretsiztakipci6612@ucretsiztakipci66127 күн бұрын
  • Zoran Im a active Patreon subscriber and your videos are always helpful!. To be honest your videos make me uncomfortable (in a good way). It pushes me to find my gaps and progress my abilities. Thank you!

    @jonathanmccarthy3985@jonathanmccarthy39854 ай бұрын
    • Thank you for your support!

      @zoran-horvat@zoran-horvat4 ай бұрын
    • Your comment so perfectly describes how I feel also. I really value this mans content

      @jeremychristman1515@jeremychristman15154 ай бұрын
  • Great video Zoran! The last code presentation is not quite readable for me but I definitely would use functional programming due to its shortness and mutable resistance in general. 🤩

    @_IGORzysko@_IGORzyskoАй бұрын
  • Thanks! It was hard but very exciting!

    @HOSTRASOKYRA@HOSTRASOKYRA4 ай бұрын
  • very interesting video, i myself try to use some more modern syntax of csharp, it is usually an iterative process, balancing human readability, syntax and performance

    @yufgyug3735@yufgyug37354 ай бұрын
  • Your videos are very educational. Keep up the good work!

    @dzllz@dzllz4 ай бұрын
  • Awesome techniques. Very educational. Thank you for your effort!

    @VladimirRoytman@VladimirRoytman3 ай бұрын
  • Mind. Blown.

    @jrandallsexton@jrandallsexton16 күн бұрын
  • I do the FP styled code most of the time in my daily work, including using method groups as delegates (especially so even). My personal style is to do a bit less in expression bodied methods as i find the fellow who didn't write it lay struggle to read it, also still haven't taken the time to use all the Linq methods i could. Though my past experiences affect that as i used to write code where an IEnumerable was an ungodly memory hog very easily and Linq methods could easily box in not just the obvious variable but half a function chain. Learning off the aversion where appropriate (even the C#12 Linq simply doesn't hold a candle to careful proc code on blazing paths, but those are slow to write without bugs)

    @RiversJ@RiversJ4 ай бұрын
  • I like this condensed abstracted format you have begun making where you iterate on a simple example. It really helps highlighting not just the "how" but the "why". My personal "why" has mostly been a feeling I have had for a few years, but that does not go far in persuading colleagues. Now, a few questions - some could be viewed as thinly cloaked critiques, but they are posed as questions since I might be missing something: 1) In your final iteration, your parameter is repeatedly named `tuple`. Referring to your comment at 3:33 ("name after purpose, not type"), surely this should be `state` (or similar), no? 2) In your switch expression, the second and fourth case differ only on `count` (`1`, `2`, respectively). Could they not be collapsed to a pattern matching on `(var max, _, 1 or 2)`? 3) Your l.50 at 4:22 seems to be sacrificing security for brevity: Dereferencing `all[0]` and `all[1]` three times looks like a bug magnet to me. I would prefer a preceding line with `var (first, second) = (all[0], all[1])`, would you agree? Might there be a way to inline it, so as to get both brevity and security? 4) While using pattern matching switch expression, I find it easy to get lost in the details because the patterns themselves cannot be abstracted away and given names. Surely switch patterns can be used in both "good" and "bad" ways. I would love to see this addressed in a future video.

    @aalasso2@aalasso23 күн бұрын
    • I agree with your comments. There will be some videos about the switch expressions and pattern patching expressions.

      @zoran-horvat@zoran-horvat3 күн бұрын
  • Happy new year!! Now, I can be free to use "when" clause in switch expression body and many thanks for great tutorial. Btw, it seems the seed values for the max and the next in functional variations should be int.MinValue instead of 0.

    @okcharles7@okcharles74 ай бұрын
    • No need for int.MinValue because there is count set to 0 to invalidate both values initially.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat you are right. Actually, what I thought was, those initial values could have made the switch case shorter, for example of Pure version: (var m, _, var c) when num > m => (num, m, c+1), (var m, var n, var c) when num > n => (m, num, c+1), _ => tuple with { count = tuple.count + 1 }, However, after your reply, I found this rule could be applied to all the cases and your intention was to apply the same logic for all.

      @okcharles7@okcharles74 ай бұрын
  • I think I would've clumsily reduced it to about 6 Linq statements. Something like: var result = items .Select(n => int.TryParse(n, out var val) ? (int?)val : null) .Where(n => n.HasValue) .OrderByDescending() .Take(2) .ToArray(); return result.Length == 2 ? result.Sum() : -1;

    @billy65bob@billy65bob4 ай бұрын
    • You should use .OrderDescending() and result.Sum()!.Value for the code to compile - it's probably the most concise functional solution. There's at least this interesting but rarely discussed factoid that C# automatically lifts operators to nullable which is why this approach works in the first place.

      @spacepigs@spacepigs4 ай бұрын
    • That takes O(N logN) time and O(N) space for an unknown N. Only if requirements guaranteed that N is small could we try this condensed approach. The requirements from the video are open to the possibility of working with extremely large inputs, and so I have implemented an O(N) time and O(1) space algorithm.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • The pure method is beautiful! I love the Aggregate method of boiling down an IEnumerable to a single output, it can be used for tons of use cases. My challenge is seeing the pattern. Moving from OOP to FP requires you look at the requirements from a different perspective. Sometimes, when I cannot see the FP solution right away, I will write it in OOP and then refactor until it is something elegant and pure. Thanks Zoran!

    @christensencm@christensencm4 ай бұрын
  • I really enjoyed this video. It's a great overview of modern programming and oddly enough I'm currently looking into functional programming to see if I can snatch paradigms and bring them over to C#. My main question as a game developer... do I need to be concerned for performance employing such a style of programming?

    @friedcrumpets@friedcrumpets4 ай бұрын
    • Game development has a large part that is performance critical, both in terms of CPU-bound operations and garbage collection. In that respect, most of the advice I gave in this video (and most other videos on my channel) is not good advice for game developers. On the other hand, all the techniques I show are tried and tested in business applications and services, where you can truly cut your codebase in half.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • As a unity developer myself, I can assure you that you can effectively use some form of functional programming in game development. Sure making everything immutable and creating copies everywhere is not a good idea when we are working with large objects, but using pure functions in the underlying logic is largely feasible.

      @soverain@soverain4 ай бұрын
    • I use Option monads and Linq all the time in Unity. It is not a concern unless the profiler tells you so. Most of the time performance issues are in asset memory allocations (uncompressed textures etc)and loading said assets. Async functional code and Profiler are your friends.

      @Bankoru@Bankoru4 ай бұрын
    • @@Bankoru I've just had a google of Option Monads; something I've seen explained by here before and used before without realising. Thanks for the responses on this, actually really helpful 👍

      @friedcrumpets@friedcrumpets4 ай бұрын
  • I like using these tricks to shorten my code, but I've noticed that sometimes it has a tendency to make the code less readable, so I try to balance those things

    @MrFalcon58199@MrFalcon581994 ай бұрын
    • Actually, the game is to train your eyes to see expressions, rather than statements. Once you get over that, you will start reading mappings and expressions fluently, and it will be imperative constructs and block statements that will hurt readability.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat Yes! In the end, it's all about conventions. One could easily argue that a for loop makes looping more difficult to understand, because all of the looping logic is contained in one piece of syntax and you need convention around how to interpret the syntax for it to be unambiguous. I for one am very happy to see more and more functional "conventions" make it into languages like C#. Yes, they may seem foreign at first and it takes time to integrate them into your own vocabulary, but they bring so much additional expressivity in the way they convey intent, it's almost crazy to think that I ever coded without them!

      @JaconSamsta@JaconSamsta4 ай бұрын
    • @@JaconSamsta Same with me, and my colleagues testify in the same spirit. Once you get there, you only turn back when there is justification: an express request for performance, an in-place algorithm, multipass algorithm, etc.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Wow, just beatuiful, thank you.

    @victorcomposes@victorcomposes4 ай бұрын
  • I can honestly say that I'm writing code with pattern matching et al. Just the last step with delegates and Linq to make. Awesome Zoran.

    @nickbarton3191@nickbarton31914 ай бұрын
  • I like the last example. I think the difficulty lies in the lack of understanding of the Aggregate method more than the code itself.

    @soverain@soverain4 ай бұрын
    • That was exactly my point. Once you switch your mind to seeing expressions, you start feeling odd when faced with something that is not an expression.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • Aggregate ( TAccumulator seed ,

      @okcharles7@okcharles74 ай бұрын
    • I like the Aggregate method (i.e. "reduce" everywhere else) but I tend to not use it because let's face it, it's hard to read. And even if you master it, other devs reading your code will struggle.

      @daaa57150@daaa571504 ай бұрын
    • To be very pedantic, we used the aggregate function but didn’t count the lines of it. Nevertheless, great example for moving from traditional object oriented to functional. Is there a video on map-reduce concept (not just the LINQ functions) in C# already by you? If not please make one. I have always struggled to recall it as it’s not used everyday.

      @hemant-sathe@hemant-sathe4 ай бұрын
  • I have actually come back to this video, and honestly I it's incredible just how many fewer memory allocations there are with the functional approach. I ended up settling with this implementation which uses the same memory usage, but is easier for me to read. public static int SumOfTwoLargest(IEnumerable items) { var result = items .Select(item => { int.TryParse(item, out int number); return number; }) .Aggregate((max: 0, next: 0, count: 0), (acc, number) => acc.count switch { 0 => (number, acc.next, 1), 1 => number > acc.max ? (number, acc.max, 2) : (acc.max, number, 2), 2 when number > acc.max => (number, acc.next, acc.count), 2 when number > acc.next => (acc.max, number, acc.count), _ => acc }); return result.count == 2 ? result.max + result.next : -1; }

    @1992jamo@1992jamo3 ай бұрын
  • Can u make video about reflection and attributes im confused in that one

    @avaygc5646@avaygc56464 ай бұрын
  • Great content

    @logantcooper6@logantcooper64 ай бұрын
  • Hi Zoran. How to find a bug in the middle of a long, chained LINQ expression? Do you use the QuickWatch window or do you use another technique?

    @AndersBaumann@AndersBaumann4 ай бұрын
    • Why would you make a long, chained LINQ expression? If there are many operations to chain, I would expect to see them split into logical sections. If an operation makes a complex transform, I would expect to see that transform pulled out into a separate method or a function. The rules of managing complexity in LINQ are the same as in any other portion of code - don't let the code grow beyond a limit you can manage.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • You discuss separate domain from infrastructure. My question is what are other names/concepts of infrastructure.

    @muhammadumair9074@muhammadumair90742 ай бұрын
  • Brilliant.

    @vivekkaushik9508@vivekkaushik95084 ай бұрын
  • How good is the last "ulatimate" solution in terms of performance compared to the procedural approach? I see a lot of function calls there.

    @varagor23@varagor234 ай бұрын
    • It is the job of a compiler, especially the JIT compiler, to inline those calls. You should train your eyes to view code through transforms and not through CPU instructions, mostly because anything you imagine will execute on a CPU is probably not true. It is indicative that either approach would accumulate to no more than 0.1% of execution time if execution includes loading the data from persistent storage, and to way under 0.05% of time if producing the response would include network transfer to a distant location. In other words, execution time is irrelevant. Development time, extensibility and bug count are the primary concerns for an engineer.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • I was curious too, so ran some Benchmarks. In terms of performance, both "functional style" versions perform better than the more procedural styles. The "Functional" version seemsto consistently perform the best out of the 4, and personally seems the more universally readable of the two functional styles to me, so I'd go with that style personally. They also don't require any allocations unlike the more procedural versions, which tends to be the more common limitation I've come across. | Method | Count | Mean | Ratio | Allocated | Alloc Ratio | |--------------------- |-------- |------------------:|------:|----------:|------------:| | ProceduralMethod | 0 | 2.560 ns | 1.00 | 32 B | 1.00 | | ObjectOrientedMethod | 0 | 2.613 ns | 1.02 | 32 B | 1.00 | | FunctionalMethod | 0 | 1.275 ns | 0.50 | - | 0.00 | | PureMethod | 0 | 12.430 ns | 4.86 | 128 B | 4.00 | | | | | | | | | ProceduralMethod | 1 | 20.769 ns | 1.00 | 112 B | 1.00 | | ObjectOrientedMethod | 1 | 20.779 ns | 1.00 | 112 B | 1.00 | | FunctionalMethod | 1 | 13.387 ns | 0.64 | 40 B | 0.36 | | PureMethod | 1 | 25.185 ns | 1.21 | 168 B | 1.50 | | | | | | | | | ProceduralMethod | 10 | 128.382 ns | 1.00 | 288 B | 1.00 | | ObjectOrientedMethod | 10 | 137.218 ns | 1.07 | 304 B | 1.06 | | FunctionalMethod | 10 | 95.041 ns | 0.74 | 40 B | 0.14 | | PureMethod | 10 | 126.616 ns | 0.99 | 168 B | 0.58 | | | | | | | | | ProceduralMethod | 100 | 1,056.616 ns | 1.00 | 1256 B | 1.00 | | ObjectOrientedMethod | 100 | 1,121.603 ns | 1.06 | 1272 B | 1.01 | | FunctionalMethod | 100 | 903.564 ns | 0.86 | 40 B | 0.03 | | PureMethod | 100 | 1,040.499 ns | 0.98 | 168 B | 0.13 | | | | | | | | | ProceduralMethod | 1000 | 10,481.245 ns | 1.00 | 8496 B | 1.000 | | ObjectOrientedMethod | 1000 | 12,829.850 ns | 1.22 | 8512 B | 1.002 | | FunctionalMethod | 1000 | 10,251.213 ns | 0.98 | 40 B | 0.005 | | PureMethod | 1000 | 11,721.219 ns | 1.12 | 168 B | 0.020 | | | | | | | | | ProceduralMethod | 100000 | 1,378,139.537 ns | 1.00 | 1049162 B | 1.000 | | ObjectOrientedMethod | 100000 | 1,639,344.766 ns | 1.19 | 1049132 B | 1.000 | | FunctionalMethod | 100000 | 1,212,847.956 ns | 0.88 | 41 B | 0.000 | | PureMethod | 100000 | 1,321,638.203 ns | 0.96 | 169 B | 0.000 | | | | | | | | | ProceduralMethod | 1000000 | 17,178,708.152 ns | 1.00 | 8389238 B | 1.000 | | ObjectOrientedMethod | 1000000 | 19,084,339.955 ns | 1.11 | 8389254 B | 1.000 | | FunctionalMethod | 1000000 | 12,412,192.083 ns | 0.72 | 46 B | 0.000 | | PureMethod | 1000000 | 13,565,147.292 ns | 0.79 | 174 B | 0.000 |

      @theramblingbrit4431@theramblingbrit44312 ай бұрын
  • I would have thought you will put the tuples into using aliases. And I'm sure there is a reason why. Would you care to elaborate? Thx

    @Luke-me9qe@Luke-me9qe4 ай бұрын
    • Actually, I was thinking about doing that but eventually dropped the idea. Maybe I could play a bit with that in a separate video.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • if I saw the last approach in a PR I would nope out

    @johnsuckher3037@johnsuckher30374 ай бұрын
    • So, your mind is not there yet. That is not a problem - keep learning.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat i do understand it... and i'd still reject it. Not because its bad code, but because i'd be the only one on the team that could maintain it, present or future.

      @adambickford8720@adambickford87204 ай бұрын
    • @@adambickford8720 I was leading one such team and I have invested a lot in explaining this programming method. One of the members came to me a couple of years later to tell me that the team is still doing it that way, and that they would never trade it for their prior practices. I have never accepted the lack of education among the programmers I worked with. It is fine to not know something - there are tons of technologies I encounter daily and I don't know them. Not knowing is normal. But it is absolutely unacceptable to stick to sub par designs and refuse to learn better. I have done it through my career as a developer, as a team lead, and as a CTO - and it worked every time. But learning must be demanded explicitly. I never left it as an opt-in choice to my colleagues.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat we have had very different experiences! My employers have *actively resisted* that kind of solution because it requires 'rock star' devs and has too much risk. They can't afford "ivory tower" solutions that require additional ramp up time educating a team. They want the most fungible cogs possible as they expect the code to far outlive the team. That kind of code becomes some esoteric thing written by the greybeards of yesteryear nobody dares touch. TBC, it's incredibly frustrating to me the answer is to dumb down the solution instead of leveling up the devs. But the reality is I have to fight tooth-and-nail just to get people to use a 'reduce' properly. And when they report 'the PR works, but it's a hack' the boss will choose 'done right now' over 'done right' every time.

      @adambickford8720@adambickford87204 ай бұрын
  • The Discord link is broken - is Discord available for everyone? I love you content. Took me a long time to find someone with conceptual understanding and broad vision even though I am beginner at C#. There are a lot of simple solutions on TY but no one give answers to "why that desing? why that solution?". Big thanks!

    @chrisspire@chrisspire2 ай бұрын
    • Try now. I have replaced the link with a redirect link that should always be up to date.

      @zoran-horvat@zoran-horvat2 ай бұрын
    • @@zoran-horvat All good now. Thanks!

      @chrisspire@chrisspire2 ай бұрын
  • It reminds me the old days of C. When you open a .h file, y will see one line with 120 characters ( in 80x25) and wonder what it does and how. Sorry, im too old for these: if I need more than 10" to understand a part of a code, this code needs either a comment or refactor it.

    @1Eagler@1Eagler4 ай бұрын
    • Thirty years ago t'was an' it ain't no C these years no more.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat '87

      @1Eagler@1Eagler4 ай бұрын
  • Pretty solid code, i can tell that folding through the use of an FSM is kind of a pattern for you.

    @kostasgkoutis8534@kostasgkoutis85344 ай бұрын
  • My worry with C# having so many different ways to do things in the same language is that when you have a shared code base with lots of different people, there will be lots of different "flavours" or styles and implementation techniques using different styles of the language ... i.e its going to encourage inconsistency. But then on the flip side, it makes the language so powerful and means it can be used in more places. So yes, I'm not entirely sure how I feel about the current direction of C#.

    @SirBenJamin_@SirBenJamin_4 ай бұрын
    • It is common nowadays to split large domains into smaller components - services, vertical slices, all sorts of them. I don't expect different styles to flourish within a single component if it is small enough.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Nice approaches but, how about performance between each approach, which is better?

    @DanielOliveira-hd9uc@DanielOliveira-hd9uc4 ай бұрын
    • What is performance when the data is loaded from storage, transformed, and then sent over the Internet? Whatever you write, and whichever coding style you adopt, the time your code takes will never approach one percent of the request-response time.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat While this is true, if you concede that this approach may not be suitable for something like Game development, and if you are advocating that people should adopt a more functional approach to their C# development - I think spending a minute or so being transparent about the performance of each approach would be welcome, even if it's negligible in 95% of use-cases.

      @conbag5736@conbag57364 ай бұрын
    • @@conbag5736 The primary target of C# are business applications. Game development, system applications, embedded systems, operating system - you can do most of that in dotnet, but you should know on your own what tradeoffs each includes and how it differs from mainstream programming.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • I ran a benchmark for the OOP, Functional and Pure cases. Surprisingly, functional had the best performance, followed by Pure (~18% slower), then OOP(~26% slower). In terms of memory allocation, OOP is surprisingly high (almost x1000 higher than functional in the 10000 strings case). I wish I could just post the table here. I find the pure case more interesting, but certainly less readable. Overall I'd stick to functional in this particular case (better performance/readability/memory) despite it not even using Linq (and it is faster specifically because it doesn't, although performance difference is negligible).

      @Bankoru@Bankoru4 ай бұрын
    • @@Bankoru The first two solutions collect the data into the list, and the last two don't - that is the difference in memory. Regarding CPU, I am not surprised to see the last two solutions coping well because all four solutions execute the same arithmetic operations in the same order, with only minor differences caused by the compiler optimizing them differently. Therefore, under the line, all that counts is the code structure on the screen, and that is where we can benefit the most from more expressive forms - functional design and expressions.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Another great video from Zoran! I do wonder if Microsoft are having ideas of merging C# and F# into a single language one day.

    @dwhxyz@dwhxyz4 ай бұрын
    • I suppose not. Those are two views on software design.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • ​@@zoran-horvat They are but with the rise in popularity of functional style programming along with what has been added to C# over the years has made me think there could be plans for this one day or to phase one of them out. I'm thinking quite some time in the future - 10+ years.

      @dwhxyz@dwhxyz4 ай бұрын
  • I would love to see the performance for each method, for example the enumerator will add overhead when lowered to IL.

    @RicusNortje@RicusNortje4 ай бұрын
    • There is an analysis in the comments. Contrary to what many opponents of modern C#, it turns out that the two functional variants are the fastest. I expected that because I have seen it so many times already.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • Hey, I had the same thought so tested it, and wrote about it here: blog.onelivesleft.com/2024/01/modern-c-performance-in-brief.html

      @sideshowfrost@sideshowfrost4 ай бұрын
  • In the object oriented example you could reduce the curly braces to 0 if you remove the braces on the for each loops since c# counts the code in both of them as a single line so it is valid. And you also save some lines

    @patfre@patfre4 ай бұрын
    • In a traditional code formatting style, that is usually considered an extreme and dangerous practice. I have nothing against it, personally.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat I also have nothing against it personally because of the fact that it’s in the way I format my code makes it easier for me personally to see what it does but I am also against it in certain cases like if else statements I wouldn’t do it but if it was just a single if statement I usually do it to make it simpler. I do also understand that it may not be the best I understand both sides here

      @patfre@patfre4 ай бұрын
  • Typed this code out and traced it in debug. Double awesome ! About readability, is it possible to use an alias for the tuple ? The tuple structure is repeated half a dozen times and makes it look busy. I tried an alias but couldn't make it compile, needs C# 12. I converted to a struct using ReSharper and made it immutable but it needs a constructor, deconstruct; just ugly.

    @nickbarton3191@nickbarton31914 ай бұрын
    • I feared you would come with a bug report. I never ran that code while I was working on it :) All I know about its correctness comes from my trust in the development method I applied.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat It works great, even with a list of 1 or 0 items and also negative numbers. I'm just saying it's a little verbose with the repetition of the tuple.

      @nickbarton3191@nickbarton31914 ай бұрын
    • Actually, I rewrote it using a SortedSet of the largest numbers instead of a tuple with another aggregate to sum them. IMHO, it's simpler and can be parameterized for how many max values to sum. Same line count. But I appreciate the demo of C# features, for me it's having the wisdom and experience to know how and where to use them instead of procedural style. I wonder also about performance, are there pitfalls to avoid? I need to prototype more before changing production code. Time is the enemy! In theory, I'm not allowed at the laptop in weekends 🙃

      @nickbarton3191@nickbarton31914 ай бұрын
    • @@nickbarton3191 SortedSet removes duplicates. If you wanted to go that way, the SortedList is the right collection to use.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat Quite right, depends on the exact requirement I suppose but I didn't think about it.

      @nickbarton3191@nickbarton31914 ай бұрын
  • I love it, but my tech lead hates I even use expression bodied methods.

    @Bankoru@Bankoru4 ай бұрын
    • I know of cases like that...

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Late 20th century code - I’m going to borrow that line ! Problem is we get taught to do that then when we get a job, it’s hard to unlearn this.

    @coderider3022@coderider3022Ай бұрын
    • I know. I've been there, I've done that - for a decade at least. The good thing is that all this I am teaching exists in books. That is how I found about the problem through my career and then gradually improved.

      @zoran-horvat@zoran-horvatАй бұрын
  • Since I have a habit of benchmarking competing solutions for the same problem before picking one, I benchmarked each approach from this video. I tested 1, 5, 10, 100 and 1000 input items, all random from range (-4096, 4096) - using a fixed seed number for consistency. The last two methods win on memory allocation, which was constant (40 bytes on my machine) - so they scale best in that regard. The third method wins on performance, while the last one was sometimes twice as slow (even slower than the first two). Note that I ran this on a potato (2009 Macbook running Linux Mint), so the results may be different on something less ancient, but I'd expect the relative numbers to be just the same. So I guess the moral of the story is: BenchmarkDotNet is your friend :)

    @inzyster@inzyster4 ай бұрын
    • I plan to make a video on benchmarking, too. But you should be aware of the overall operation. Since each of the methods completes in microseconds, and data fetching that involves persistent storage would cost milliseconds, these methods are entirely irrelevant in the holistic performance analysis. Each variant is acceptable, so the decision is with maintainability, flexibility, and other -ilities that we need in software development.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • I did some benchmarking as well. I tested list sizes of 10, 100, 10_000, and 1_000_000. I generated a random set of numbers (same set each run, generated outside the benchmarks so won't influence the runtime or memory scores) and stored them in an array (so minimal overhead on enumeration). .NET 8. Ryzen 3700 CPU. BenchmarkDotNet v0.13.12 I think the most surprising was that MagicSum1 was slower than MagicSum0. These are basic syntactic sugar improvements, but MagicSum1 was ~5% (size 10 and 100) to 25% (size 10_000 and 1_000_000) slower than MagicSum0. Meanwhile, memory usage comparisons between MagicSum0 and MagicSum1 were a bit confusing. It varied between MagicSum1 using twice as much memory, to MagicSum0 using twice as much memory. Not sure why things varied like that. MagicSum2 and MagicSum3 were a vast improvement on memory allocation, using almost none regardless of data set size since they don't convert all the strings to a list of ints. However speedwise, MagicSum2 substantially outperformed MagicSum3. MagicSum3 was the slowest of all the algorithms for all data set sizes aside from 1_000_000, where it returned to being on par with MagicSum0. On the other hand, MagicSum2 was always the fastest, ranging from 10% to 20% faster than MagicSum0 (what I used as the baseline). For 1_000_000 data points, the difference between the worst (MagicSum1) and the best (MagicSum2) was 10 milliseconds (MagicSum2 being 35% faster than MagicSum1) and 13 MB of allocations. There was also a 5 millisecond difference between MagicSum2 and MagicSum3. I also tried making a variant which used MagicSum2 as a base, but using explicit if checks to see if the self-assignment of the default switch condition caused any additional performance overhead. The performance of the two variants was basically identical within the noise level, so the "syntactic sugar" penalty we saw going from MagicSum0 to MagicSum1 isn't hurting MagicSum2. Same when switching MagicSum3 to a generic variant. Overall, I'd say that MagicSum2 is the best for performance, memory, and readability. MagicSum3 is OK if you prioritize composability over the other metrics, and I think would also be preferable for generics (as long as performance isn't a major concern). So yes, go for modern code and pattern matching no matter what, but the step towards composed functional programming still needs additional thought based on your particular needs.

      @David-id6jw@David-id6jw4 ай бұрын
    • @@David-id6jw Thank you for this input. You have got the point that the greatest advantage of the GetMagicSum3 is composability, which is favored more than speed in functional designs. However, its speed primarily depends on how the patterns are selected. I did literally nothing to help the compiler and that is the native result of letting the compiler do it all for us. The principal reason why we don't try performance optimizations in FP first is that the data crunching code is way faster than I/O anyway. Any function that requires I/O before and/or after data processing will take as much time as I/O dictates, with or without optimization of its CPU-bound part.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Hi @zoran-horvat, I'm one of many developers out there that are still struggling to understand and shift our comprehension and perspective into a functional paradigm. I'm also not the brightest one I would say. So my question is, how can we improve ourselves, make it familiar, and to get better in this topic?

    @robypeng@robypeng4 ай бұрын
    • Read everything you can grab. Learn every day. I have been doing that for the last 20 years and that has become my way of life ever since.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Awesome

    @luc9volts@luc9volts4 ай бұрын
  • string[] nums= ["1","2","3","4","NAN","77","dude","23"] // modern syntax i prefer is 4 lines int sumlargest2 = nums.Select(x=>int.TryParse(x,out int i32)?i32:0) .OrderByDescending(i=>i) .Take(2) .Sum();

    @antonknieriemen8682@antonknieriemen86824 ай бұрын
    • That makes an assumption of a small sequence of strings. Since that assumption is not listed in the requirements, your solution is not acceptable under the current requirements.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • F# is a lot of fun.

    @TreeLuvBurdpu@TreeLuvBurdpu4 ай бұрын
  • The primary mistake here is measuring by LoC, which you very well reduce by including both the if statement and the code statement if the same line, which would otherwise be 2 or more lines. This greatly hinders readability, much like how the more "advanced" methods do. The point is not to write clever and short code, but readable and fast enough for your use case. The only thing I can commend for in this video is the showcase of C# features that everyone writing C# should definitely know. But returning magic tuples instead of declaring record structs for them comes against the point of the video, which is showing advanced C# features that people should be using in their code.

    @AlFasGD@AlFasGD4 ай бұрын
    • I believe my point should have been made from the other end, though I'm not sure if I could communicate it well to the audience: _if_ you choose to design behavior in functional style, rather than object-oriented or procedural, _then_ you will have the novel syntax at your disposal and _that_ will help make your code shorter by a factor of two.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Brilliant implementation! Can I give constructive criticism? Instead of using Aggregate, isn't the classic foreach loop better in terms of performance and readibility code? Something like this code: int MySumMethod(IEnumerable items) { (int max, int next, int count) tuple = (0, 0, 0); foreach (var item in items) { if (int.TryParse(item, out int number)) { tuple = tuple switch { (_, _, 0) => (number, 0, 1), (var max, _, 1) when number > max => (number, max, 2), (var max, _, 1) => (max, number, 2), (var max, _, 2) when number > max => (number, max, 2), (var max, var next, 2) when number > next => (max, number, 2), _ => tuple }; } } return tuple.count == 2 ? tuple.max + tuple.next : -1; } What do you think? Thank you

    @az6876@az68764 ай бұрын
    • Once you see why Aggregate is better, you will never look back. Here is what makes it better: it _forces_ you to have an explicit transform. Without it, there is no barrier to stop your codebase from becoming 100% procedural, losing every single benefit you could get from having explicit small, composable transforms.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • Hi @@zoran-horvat thanks for your reply. My criticism of the procedural whole is based not on the goodness of the code, which I do not discuss (on the contrary, I like it very much as in your implementation), but on the performance (and in my job I have to control that). If I do a trivial benchmark test between the Aggregate and foreach mode I proposed, I get these results: | Method | Mean | Error | StdDev | Gen0 | Allocated | |------------- |---------:|--------:|--------:|-------:|----------:| | GetMagicSum3 | 253.7 ns | 4.79 ns | 4.48 ns | 0.0253 | 40 B | | MySumMethod | 129.9 ns | 1.63 ns | 1.36 ns | 0.0253 | 40 B | This is one of the problems with this approach: apart from the readability of the code, which can be confusing for the inexperienced, the performance is often inferior (very high number of jumps, stack, etc...) and this is what still stops me in the all-procedural approach. At the moment I prefer a 'mixed' approach.

      @az6876@az68764 ай бұрын
    • @@az6876 You are discussing 0.1 microsecond where even the simplest database query or file request that would feed the data in takes at least 1ms. There is no point in optimizing one 10,000th part of execution time.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • ​@@zoran-horvat no, it's not 1ms, but 40% less time. In a realtime context it makes a lot of difference.

      @az6876@az68764 ай бұрын
    • @@az6876 LINQ is not made for realtime applications, nor is C# for that matter, not even foreach. And, obviously, it is not 40% - for actual percentage, you must include the data fetching and result dispatch time. If that includes any I/O, as it does, then that 40% drops down to well under 0.1%.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Our brains must be programed to think this way through repetition.

    @lee1davis1@lee1davis14 ай бұрын
    • Precisely. I haven't met a programmer who didn't understand this process. But I have heard numerous team leads who say their team members cannot understand it. Those leads believe their colleagues are incompetent.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • one line int sumlargest2 = nums.Select(x=>int.TryParse(x,out int i32)?i32:0).OrderByDescending(i=>i).Take(2).Sum();

    @antonknieriemen8682@antonknieriemen86824 ай бұрын
    • That algorithm requires O(N logN)) time and O(N) space. You cannot assume that is allowed unless requirements clearly state it is, e.g. by giving an acceptable upper bound for N. The solution from the video makes no such assumptions. It produces the result in O(N) time and O(1) memory.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • What about this approach? int SumOfLargestTwo(IEnumerable source) => source.Aggregate( (default(int?), default(int?)), (current, next) => current switch { (var x, var y) when x is null || next > x => (next, y), (var x, var y) when y is null || next > y => (x, next), _ => current }, r => (r.Item1 + r.Item2) ?? -1); // ((x,y)) => (x+y) ?? -1 in the future

    @rauberhotzenplotz7722@rauberhotzenplotz77224 ай бұрын
  • Instead of a tuple, I would have used a locally defined immutable record. The tuple requires the definition to appear multiple times, increasing cognitive overhead unnecessarily.

    @zumalifeguard3493@zumalifeguard34934 ай бұрын
    • In many places in code it is not a tuple but an assignment to several variables. On the other hand, stepping from ValueTuple to a record class may require careful consideration of performance, especially if it is instantiated many times in a loop.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • Good point with regard to performance.

      @zumalifeguard3493@zumalifeguard34934 ай бұрын
  • While code readability is an important aspect (Prefer understandable over clever code) - All those syntactical improvements are exactly why modern C# feels so much better than Java. Java is still almost stuck in the imperative phase, while we have a vast array of choices to pick from.

    @allinvanguard@allinvanguard4 ай бұрын
  • Impressive coding skills. Still, I would not recommend using that kind of advanced c# in an Enterprise project. Simply because all teams members won't have the same skillset - this type of code will be a paria that only one or two developers will dare touching. After 5 years it will be known as the code with technical debt. IMHO, writing the shortest/smartest code is something you do when you have a small dedicated team. In an Enterprise, writing easy to read code is king for long levity.

    @Lazzerman42@Lazzerman424 ай бұрын
    • I am trying to communicate the opinion that code based on expressions, pattern matching, and value mapping is also the simplest and easiest to understand. I have done that in my teams and, once you put things that way, members on the team accept it. You should not fear giving your colleagues an opportunity to learn.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat In my experience - things that are truly good, will be simplified by time. In other words, pattern matching syntax and functional program seems immature - but will probably mature and get better tooling support and "better" syntax if they bring business value. Happy new year!

      @Lazzerman42@Lazzerman424 ай бұрын
    • @@Lazzerman42 I am sure these constructs will be even simpler in the future.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • Even though I follow the changes carefully I am getting a little bit worried about the direction of the language. Even though this is readable, and we implement somewhat a single responsibility principle, I would argue that the simplicity is getting lost in the syntax. But that’s just me.

    @mdev3987@mdev39874 ай бұрын
  • Wow

    @ClickOkYT@ClickOkYT4 ай бұрын
  • Does the shortened code actually make it run significantly faster? If not then it's a waste of time because all you are doing is making it much harder to read, understand and ultimately maintain. This is why shorthand completely fell out of use, sure it was compact and efficient to write but almost nobody could read it.

    @IvarDaigon@IvarDaigonАй бұрын
    • The final code is an expression. Your comment indicates that you prefer procedural code over declarative, and that is so 1980s. The sooner you rid that mindset, the better for you, trust me. There is a very simple empirical proof for that. I know many programmers personally who made that step and none of them ever turned back to say that expressions are not readable or something. That tells you should learn to favor expressions, too.

      @zoran-horvat@zoran-horvatАй бұрын
  • The last version is unreadable to me :(

    @zimpoooooo@zimpoooooo2 ай бұрын
    • A matter of training the eye. Trust me, soon enough all code will look like that.

      @zoran-horvat@zoran-horvat2 ай бұрын
    • @@zoran-horvat Btw, great thought provoking videos, even if I may not necessarily adopt the style.

      @zimpoooooo@zimpoooooo2 ай бұрын
  • Last two xd

    @hashemwannous374@hashemwannous37414 күн бұрын
  • 😁 have no insightful comment other than the emoji, anyway, thank you man.

    @PeacefulMindss@PeacefulMindss4 ай бұрын
  • Really interesting, but i think it could also work without the need of handling the count variable simplifying the Advance method

    @banster85@banster854 ай бұрын
    • The method must distinguish the case when there are less than two items in the sequence from other cases.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • I mean something like this: return number > tuple.max ? (number, tuple.max) : number > tuple.next ? (tuple.max, number) : (tuple.max, tuple.next); This should work regardless the value of the count variable

      @banster85@banster854 ай бұрын
    • @@banster85 But what about the case when there are no two numbers in the sequence?

      @zoran-horvat@zoran-horvat4 ай бұрын
    • ​@@zoran-horvatin this case the next variable will remain with its initial value 0 so the ProduceSum method can do the check on this variable, if zero returns -1 otherwise the sum​

      @banster85@banster854 ай бұрын
    • @@banster85 What if the input number is zero?

      @zoran-horvat@zoran-horvat4 ай бұрын
  • I am surprised such things are not obvious for people

    @lucifer-look-@lucifer-look-4 ай бұрын
    • You can see from the comments how many programmers fiercely oppose this style, holding on to the practices that are decades old.

      @zoran-horvat@zoran-horvat4 ай бұрын
  • I generally agree with this channel, but damn I really dislike how unreadable the last 2 methods are. Looks a bunch of mathematical mumbo jumbo. I'd personally settle somewhere between the 2nd and 3rd variant

    @Katniss218@Katniss2187 күн бұрын
  • The ultimate lesson here is don't write your own code, use a library written by someone smarter than you. Unless you want to be the person actually writing a library like that...

    @auronedgevicks7739@auronedgevicks77394 ай бұрын
  • I will strike that code in PR review faster than light. It’s not the compiler to figure out the code It’s your F job. 1 - Readability 2 - Performance I swear to good I have enough to all of those who think that having performance issue is acceptable because you write business application.

    @oligreenfield1537@oligreenfield15374 ай бұрын
    • Performance? Oh, where have you been when another commenter has posted the results of measuring performance of the four methods? Guess what, the two functional methods are the fastest. Now you can take your preconceived opinions back. Better luck next time. Consider this a revenge of the compiler

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat False the message made by the other user show that a foreach + matching pattern is 40% faster. My points are still valid. It you work in a large team where the code is handle by 3 or 5 person you have a issue of readability and skill level no everyone is interested by MS new sugar syntax. So I Will stay on my position I Will strike that code for corporate use but for you home project go head.

      @oligreenfield1537@oligreenfield15374 ай бұрын
    • @@oligreenfield1537 How did you remove the part about performance from your opinion? You were very specific that this code is causing a performance issue that is somehow ignored because it is a business application. Now that it turned there is no performance issue, you pretend you never said it. My point is that your preconceived notion of a lacking readability is equally wrong, but you cannot see that from that 1990s trench in which you are dwelling.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • ​@@zoran-horvat just a side - note, I feel 90's apps were much more stable and bug-free (and faster) than today's 😔

      @zzzzz2903@zzzzz29033 ай бұрын
    • @@zzzzz2903 Actually, that is quite untrue. I know, I was there.

      @zoran-horvat@zoran-horvat3 ай бұрын
  • The fact that I can, doesn't mean I should.

    @PetrVejchoda@PetrVejchoda2 ай бұрын
  • I would code this 'functionally' in java streams, which are kinda like linq if you squint. I tried to avoid int specific features like `sum()`, I may not have fully understood the reqs: var magicSum = Arrays.stream("421739".split("")) .map(Integer::valueOf) .sorted(Comparator.reverseOrder()) .limit(2) .collect(collectingAndThen( toList(), twoLargest -> twoLargest.size() == 2 ? twoLargest.getFirst() + twoLargest.getLast() : -1 ));

    @adambickford8720@adambickford87204 ай бұрын
    • The problem with this solution is that it requires O(N logN) time and O(N) space to complete, where there is no upper bound on N. The solution from the video runs in O(N) time and O(1) space under the same constraints.

      @zoran-horvat@zoran-horvat4 ай бұрын
    • @@zoran-horvat I'm going for something that feels straight forward to understand and maps to the problem in an 'obvious' way. This largely avoids the low-level imperative 'machinery' without being so abstract it doesn't readily convey meaning in this problem context. If there's an actual SLA we can certainly do something in our chain to achieve that.

      @adambickford8720@adambickford87204 ай бұрын
    • @@zoran-horvat It looks like java added something similar to java 21 but, as usual, it seems more limited. I see what you're doing w/the count, it essentially acts as a state identifier vs explicitly having to match all of the parts in the pattern to infer state. It kind of reminds of using bit flags vs explicit booleans to manage things; clever, but not obvious. var patternMatching = Arrays.stream("32459722".split("")) .map(Integer::valueOf) .reduce( new TwoGreatest(0, 0, 0), (twoGreatest, number) -> switch (twoGreatest) { case TwoGreatest(_, _, var count) when count == 0 -> new TwoGreatest(number, 0, 1); case TwoGreatest(var a, _, var count) when count == 1 && number > a -> new TwoGreatest( number,a, 2); case TwoGreatest(var a, _, var count) when count == 1 -> new TwoGreatest( a,number, 2); case TwoGreatest(var a, _, var count) when count == 2 && number > a -> new TwoGreatest( number,a, 2); case TwoGreatest(var a, var b, var count) when count == 2 && number > b -> new TwoGreatest( a,number, 2); default -> twoGreatest; }, (a, b) -> new TwoGreatest(Math.max(a.a, b.a), Math.max(b.a, b.b), a.count) ); var sum = patternMatching.count == 2 ? patternMatching.a + patternMatching.b : -1;

      @adambickford8720@adambickford87204 ай бұрын
    • This avoids the O(N) space issue while still allowing for more than 2 items (does youtube block github links?): var limit = 2; var topN = stream("45432722557".split("")) .map(Integer::valueOf) .reduce( List.of(), (largestNFound, number) -> concat(largestNFound.stream(), of(number)) .sorted(Comparator.reverseOrder()) .limit(limit) .toList(), (a, b) -> concat(a.stream(), b.stream()).toList() ); var sum = topN.size() >= limit ? topN.stream().mapToInt(Integer::intValue).sum() : -1;

      @adambickford8720@adambickford87204 ай бұрын
KZhead