From C ➡️ C++ ➡️ Rust

In this video, I refactor a C function to C++ and then to Rust. I also show the equivalent Haskell code and show a comparison of number of assembly instructions generated at the end.
Links:
CodeAesthetic Video: • Why You Shouldn't Nest...
Slides and Code: github.com/codereport/Content...
Godbolt Links: github.com/codereport/Content...
Behind the scenes video: • How to Make Beautiful ...
Chapters:
0:00 Intro
0:25 Motivation
1:19 C Code
2:10 C++ Code 1
2:43 C++ Code 2 - Reformatting
2:53: C++ Code 3 - views::iota
3:36 C++ Code 4 - views::filter
4:14 C++ Code 5 - std::accumulate
5:10 C++ Code 6 - ranges::accumulate
5:54 C++ Code 7 - Ternary Operator
6:50 Rust Code
8:30 Bug in C/C++ Code?
10:23 Haskell Code
11:30 Count of Generated Assembly Instructions Comparison
13:40 Outro
Follow me on Github: github.com/codereport
Follow me on Twitter: / code_report
Follow me on LinkedIn: / codereport

Пікірлер: 849

  • @jonhdoe1395
    @jonhdoe1395 Жыл бұрын

    Congratulations, you took perfectly readable code, with a logical progression, easily debuggable and turned into a nice spaghetti. The boomer in me would say "that's what is wrong with the new generation".

  • @peterheijstek5288

    @peterheijstek5288

    Жыл бұрын

    It's declarative instead of imperative. If you know what the functions do, then the declarative code is not only more readable but also less prone to bugs because you are using functions in the standard library. The entire craft of programming is composing different pieces of code, right? This is exactly what declarative code does best Edit: as others have pointed out, in the C++ case the original comment is justifiable. I thought the parent commenter was talking about languages like rust and haskell

  • @DylanFalconer

    @DylanFalconer

    Жыл бұрын

    I know this is meant to be the pin of shame but I agree in the case of C++. It's so difficult to understand compared to the original and Rust versions.

  • @DylanFalconer

    @DylanFalconer

    Жыл бұрын

    Cool video though

  • @sohn7767

    @sohn7767

    Жыл бұрын

    C++ Version really was that

  • @esra_erimez

    @esra_erimez

    Жыл бұрын

    I was thinking the exact same thing myself. I'm glad I wasn't the only one

  • @ThePrimeagen
    @ThePrimeagen Жыл бұрын

    see the thing is that iota's greater instruction count is due to the fact that iota, being the smallest character, sometimes have the largest impact, both metaphorically and literally.

  • @El-Burrito

    @El-Burrito

    Жыл бұрын

    I just subbed to your channel, funny seeing you here

  • @alexandriap.3285

    @alexandriap.3285

    Жыл бұрын

    tf does that mean

  • @praus

    @praus

    Жыл бұрын

    @@alexandriap.3285 Yes

  • @mylkrenebjorson7244

    @mylkrenebjorson7244

    Жыл бұрын

    @@alexandriap.3285 The numbers of the instruction generated doesn't necessary mean anything.

  • @Brono25

    @Brono25

    Жыл бұрын

    Really makes you think

  • @wikinut1
    @wikinut1 Жыл бұрын

    To me, the C code is perfectly clear and readable, and the Rust and Haskell is perfectly clear and readable. However, whenever I look at C++ code like this, it looks like an accident waiting to happen with it's amazingly aggressive overloading of syntax.

  • @Brock-Landers

    @Brock-Landers

    Жыл бұрын

    The iterator being declared in the for loop triggered me.

  • @austinmajeski9427

    @austinmajeski9427

    Жыл бұрын

    I was thinking the same thing. It got less readable by the end of the C++ code. “One-Liners” are not always the best option when it comes to clarity.

  • @dixztube

    @dixztube

    Жыл бұрын

    @@austinmajeski9427 yup lol

  • @redcrafterlppa303

    @redcrafterlppa303

    Жыл бұрын

    I think of course the clear misuse of operator overloading by the standard (which is ironic by itself) is a big problem in c++ but another great problem is the baggage c++ is carrying. They constantly add new features and libraries to std which build on the old libraries and therefore they never retire old libraries. This leads to a thousand ways to write the exact same assembly instructions. Also trying to forcefully reuse older parts of the library prevents them to construct fresh and simple new APIs like in the ruet example. Hack the same code can be written in c++ if you write the required library code from scratch. So it's not necessarily a problem of the language but the rotten standard library. One argument against this line of argumentation is that they keep backwards compatibility while reusing code they can't therefore remove anyway. But as I explained this leads to bad APIs and isn't the best solution to fix incompatible libraries. A better is again the rust way. In rust every library and program declares the std library and 3rd party library versions its using. The cargo build tool is then compiling each library with its required versions and links them together. Therefore older libraries can use removed std features while being used in never applications and vice versa. This even applies to the language version and keywords. Therefore impossible combinations of libraries do not exist on rust and the rust committee is free to retire library functions and keywords replaced by better alternatives.

  • @Haranoi17channel

    @Haranoi17channel

    Жыл бұрын

    @@bram3367 I wouldn't say its overengineered. Its perfectly readable. The before... Completely different story.

  • @foxoninetails_
    @foxoninetails_ Жыл бұрын

    A big part of the point in the original video was less about this kind of reduction, and more about style - while this kind of reduction is an excellent technique to go through when you can, the actual code itself was really just an example to point out the underlying issue of code style. The process of pulling out nesting into preconditions is broadly applicable to many different situations, where this kind of code transformation is much more specific and situational.

  • @raianmr2843

    @raianmr2843

    Жыл бұрын

    Style is one axis, paradigm another. I think a better sample for this video would've been some callback heavy snippet that's unreadable but still somehow manages to pass as pure and functional. Considering the OG video was about style from within the imperative way of thinking, this would've been fairer. That said, it's really hard to come across code that is pure and badly styled at the same time. I guess this is due to the fact that most programmers start out as imperative ones and branch out to the functional world as they grow. But I do think in languages like Rust it's very natural to write `good` code similar to what is shown here because of zero/low-cost batteries-included standard libraries.

  • @arisweedler4703

    @arisweedler4703

    Жыл бұрын

    The style that even makes it possible to nest like this is impossible in the paradigm of shape thinking, of functional programming.

  • @foxoninetails_

    @foxoninetails_

    Жыл бұрын

    @@arisweedler4703 I strongly disagree. While a functional style naturally tends towards nesting less, it is still certainly possible to write deeply nested code in functional languages, and there are - albeit rarely - situations where it's needed. But the point remains: the original video's intention was to point out how to deal with nesting better in a more imperative paradigm, by making use of preconditions and early exit. Responding to that with "just change to a functional style" may indeed be the best practice path in many cases, but it misses the point entirely, and is a much less broadly applicable principle.

  • @arisweedler4703

    @arisweedler4703

    Жыл бұрын

    @@foxoninetails_ else you said, yes. Totally agree. Lisp can get pretty nested. I took a class in college that used lisp and I didn’t know what I was doing and my friends and I wrote some successful and bad code. Nested deep. And as for the point of the original video, yeah. It was like “we’re imperative, this is better” and it is, I agree. In fact, the “bug” where there are two ranges used in the control flow and yet they are off by one is no longer a bug in this new style. It is now contextualized as an intentional bounds check using one range, then a map filter / APP one-liner / shape pipeline over another, similar but different range.

  • @chrism6880

    @chrism6880

    Жыл бұрын

    I love videos about refactoring, because it's like watching a fantasy movie about a world where we have time to reduce the tech debt in our codebase

  • @cd-bitcrshr
    @cd-bitcrshr Жыл бұрын

    Love watching c++ devs argue which of their unreadable buggy code is more unreadable than the other

  • @VincentZalzal
    @VincentZalzal Жыл бұрын

    For those who are wondering, the sudden reduction in the number of instructions at -O3 starting from filter comes from the fact that the compiler was using SIMD instructions to handle multiple loop iterations at once in the previous versions, but after that, is unable to see through the views to perform the same optimization (which is disappointing). Edit: see reply below for better news!

  • @VincentZalzal

    @VincentZalzal

    Жыл бұрын

    Now I am confused... When trying the same code in QuickBench, the calculate functions get inlined, and then gcc optimizes the version with views using SIMD too, but with a way tighter inner loop... and that makes the views version 3.7 times faster than the original when operating on very large ranges. I might have made a mistake somewhere, I don't fully trust how I used QuickBench. Maybe someone else could try it out? For info, I was benching the call calculate(54, 12393243) with versions 1 vs 4 in the code_report Github repo. Edit: after further tests, it seems the views version get optimized with SIMD when inlined and using literal arguments. But when I pass in volatile ints as arguments, then I lose the SIMD optimization in the views version and the original version is now 3.4 times faster. So yeah, it is quite sensitive.

  • @pesto801

    @pesto801

    Жыл бұрын

    @@VincentZalzal I verify the same result. Any ideas where this might be coming from?

  • @VincentZalzal

    @VincentZalzal

    Жыл бұрын

    @@pesto801 No idea, I'd have to analyze the generated assembly to understand how the versions differ. We might be right on a threshold the optimizer uses to decide whether it is worth it or not to use SIMD.

  • @R4ngeR4pidz

    @R4ngeR4pidz

    Жыл бұрын

    Reduction? Am I color blind, am I not reading this correctly, or are you not reading this correctly? For -O3, they use the color blue, and the blue bars are by far the highest for the first ones, which makes no sense because -O3 would optimize the crap out of the original code so are the colors in the legend supposed to be reversed? Or, also a likely explanation: the number of instructions means nothing, without the context of what those instructions are

  • @VincentZalzal

    @VincentZalzal

    Жыл бұрын

    @@R4ngeR4pidz You are reading this correctly, blue is for -O3, and the number of instructions decreased when using views. The reason is that the code size usually increases when the optimizer starts using SIMD (versions on the left of the graph). It increases because the compiler has to add code before and/or after the main loop to handle the last few elements if it cannot guarantee that the number of elements is a multiple of the SIMD register size. So, to recap: versions on the left uses SIMD and thus have more instructions, those on the right don't use SIMD and are shorter. And yeah, as you say, the number of instructions is not necessarily a good metric for code performance.

  • @PileOPoop1
    @PileOPoop1 Жыл бұрын

    I am flabbergasted that his complaint about remove nesting was just calling functions and his solution is just to call super convoluted std c++ templated functions that make the code less readable.

  • @briannormant3622

    @briannormant3622

    Жыл бұрын

    But but, pretty lambda's and collect...

  • @eduardoalmeida4734
    @eduardoalmeida4734 Жыл бұрын

    Keep in mind that pure # of instructions may not be the only "optimization" parameter to be observed. C++ often optimizes code to run faster (having less branches) and this may lead to a few more instructions but with HUGE gains in execution time.

  • @vercolit

    @vercolit

    Жыл бұрын

    -O3 is loosely -O2 but also with aggressive optimisations that increase the code size. So usually it has more instructions, but they end up being faster. Sometimes, though, it isn't faster, because the increased size of the code increases the amount of cache misses to a poibt where it decreases performance. So imo the number of assembly instructions is simply not a great measure of performance. Very interesting to see and definitely an aspect of performance, but clearly not the only one

  • @skeetskeet9403

    @skeetskeet9403

    10 ай бұрын

    This is true of C, C++ and Rust. They all have optimizing compilers for a reason

  • @captainfordo1
    @captainfordo1 Жыл бұрын

    There are very clear ways you can make the C code less verbose while still maintaining its readability. I’m surprised you didn’t try to fix it, and instead jumped straight to C++. Edit: This is how I would write the function in C, and yes, I prefer this even to Rust. int calculate(int bottom, int top) { if (top int sum = 0; for (int i = bottom; i

  • @anon_y_mousse

    @anon_y_mousse

    Жыл бұрын

    Better, but could be better still by ensuring the bottom is even then incrementing by two each loop. Even that could still be improved, and I'm kicking myself for not thinking of it first, but by realizing that there are exactly half as many evens, possibly minus 1, in the range between the two numbers. No need to even loop.

  • @zxuiji

    @zxuiji

    Жыл бұрын

    @@anon_y_mousse The point is to add up the values though, for example in 2 to 10 you get the result 30, in 4 to 10 you get 28 via the loop, I've not been able to think of a calculation that does not involve the loop to get those values, how would you get them then?

  • @anon_y_mousse

    @anon_y_mousse

    Жыл бұрын

    @@zxuiji Another poster already did the work so I'll post their solution: b = ++b >> 1 > 1

  • @biomorphic

    @biomorphic

    27 күн бұрын

    This is the way the code should be written. Junior programmers should note the separation of the if statement, and the final return from the for loop, also how the sum initialisation is part of the block, because it is referred to the block. This is the way I write the code, and everyone should do sir. I am happy I am not the only one. This gives me hope. Well done.

  • @japedr
    @japedr Жыл бұрын

    I know that's not the point of the video, but this can be solved with a very simple O(1) implementation by using the arithmetic series sum formula. That would have very few assembly instructions also :)

  • @dwarftoad

    @dwarftoad

    Жыл бұрын

    Yes would be interested to see examples for some arbitrary input sequence. Which makes the awkwardness of needing to use C++ range's std::ranges::iota() less of a problem, but you still might need it to generate some indices to something else, so I still like Rust's terse (begin..=end) and wish C++ had something like that (especially to be used in for loops).

  • @Brmngm

    @Brmngm

    Ай бұрын

    EXACTLY!!! #$%^&*

  • @SouravDatta
    @SouravDatta Жыл бұрын

    I love how elegantly we can communicate the solution in functional languages! Here're scala and clojure and they are basically the same as Rust - I like them all! def calculate(bottom: Int, top: Int): Int = (bottom to top).filter(x => x % 2 == 0).sum (defn calculate [bottom top] (->> (range bottom (inc top)) (filter even?) (reduce +)))

  • @TheVirtualLab

    @TheVirtualLab

    Жыл бұрын

    Every time I look at scala code I think to myself that the code looks super nice. I'll have to find some time in the near future to dive more into it

  • @keychera

    @keychera

    Жыл бұрын

    +1 for clojure!

  • @Abraham18K
    @Abraham18K Жыл бұрын

    Question, why not use early return instead of using ternary operations? They are in my opinion simpler to read since you have all the exit conditions at the top and then you just have the code that you want to execute.

  • @rcoder01

    @rcoder01

    Жыл бұрын

    I'd recommend you watch the original video by CodeAesthetic. It goes a lot more into those kinds of refactors.

  • @jaideepshekhar4621

    @jaideepshekhar4621

    Жыл бұрын

    Thank you! Exactly, I HATED that use of ternary operator. Just use a guard clause.

  • @fsalmacis5993

    @fsalmacis5993

    Жыл бұрын

    It's probably because when using a ternary operator you end up with a single expression in the function, which fits nicely with declarative programming. The thing is... even if C++ has become multiparadigm over the years and has functional features, they feel more like an afterthought and are kinda::disgusting::to::the::eye(). Rust, in the other hand, was handcrafted with functional programming in mind, and the readability when coding that way really shows. But yeah, the title of the video should be "Declarative Programming from C to C++ to Rust", because an early return would be optimal if we were talking about imperative programming or OOP (which is actually very readable when done in C++).

  • @jaideepshekhar4621

    @jaideepshekhar4621

    Жыл бұрын

    @@fsalmacis5993 Ternary is fine for some cases. For cases like this, atrocious!

  • @minneelyyyy8923

    @minneelyyyy8923

    Жыл бұрын

    because its not nearly as fancy or cool looking

  • @wChris_
    @wChris_ Жыл бұрын

    When comparing assembly instructions you need to be very careful, since many instructions can execute faster than few instructions, especially when you unroll loops and use simd. Thats why its *always* better to benchmark.

  • @patrickbarrett204
    @patrickbarrett204 Жыл бұрын

    I don't understand why I would want to use any of those C++ features for this task when the original C code is perfectly logical and readable.

  • @DetectivePoofPoof
    @DetectivePoofPoof Жыл бұрын

    C++ segment: "Already here you can see by using more modern features we have created an absolute abomination the very sight of which has caused God to abandon us!"

  • @MaxAbramson3

    @MaxAbramson3

    4 ай бұрын

    Think of how much more readable the same code would be in Whiteboard C. #include "StandardIO.h" int calculate(int bottom, int top) if (top > bottom): int sum = 0 foreach bottom in top: (number % 2 == 0): sum += number return sum else: return 0; main(): println(calculate(5, 12)) // 36 println(calculate(5, 3)) // 0 So many C++ devs have spent so many years putting in feature requests that leave them feeling like they've contributed something to the whole, but we now have high level languages that take LONGER to understand and create MORE opportunities for readability and maintainability problems over the long run.

  • @Speykious
    @Speykious Жыл бұрын

    I'm sure Rust was more inspired by OCaml than Haskell. After all, the first iterations of the Rust compiler were written in OCaml.

  • @SourCloud

    @SourCloud

    Жыл бұрын

    You here LMAO?

  • @zzzyyyxxx

    @zzzyyyxxx

    Жыл бұрын

    Correct, Rust was more inspired by ML languages, however some functional aspects from Haskell still come through, such as how typeclasses and traits are similar.

  • @Speykious

    @Speykious

    Жыл бұрын

    @@zzzyyyxxx Yeah, I love that :D

  • @Speykious

    @Speykious

    Жыл бұрын

    @@SourCloud I am *everywhere,* as long as it's slightly rusty B)

  • @Hexalyse

    @Hexalyse

    Жыл бұрын

    @@zzzyyyxxx ​ Isn't ML language a repetition ? At this point, I think it's better to write meta language, not a lot more characters, and everybody will know what it's about. Or just write ML but it's also used for Machine Learning so it could be misleading.

  • @Gameplay-ps9ub
    @Gameplay-ps9ub Жыл бұрын

    The initial code wasn't perfect, not even near, but...I feel like too often people confuse short code with good code. I'm mostly coding in python and it allows to produce a lot of oneliners which do massive work. The issue is though, that quite often they end up being unreadable, which is counter productive in the long run. The first line of zen of python is "Beautiful is better than ugly." and it's the first line for a reason.

  • @shinjonmal8936

    @shinjonmal8936

    Жыл бұрын

    I disagree. When I couple a few related lines in python using ; It increases readability. But however, don't just couple all lines in one line. It decreases readability. This same concept applies to me doing other languages like C#, Javascript etc.

  • @alxjones

    @alxjones

    Жыл бұрын

    Less code is not always better, but the examples in this case (at least the Rust and Haskelll ones) are not counterexamples. They are much clearer right out the gate what they do, and even better, it's clear that they actually do what they're supposed to. Python definitely has its issues in regards to having very condensed ways to do things which are harder to read, but Python also has multiple ways to do this that are similar to the Rust/Haskell approaches def calculate(bottom: int, top: int): return sum(n for n in range(bottom, top + 1) if n % 2 == 0) def calculuate(bottom: int, top: int): return sum(filter(lambda n: n % 2 == 0, range(bottom, top + 1))) The ugly lambda syntax and right-exclusive ranges make it a bit less attractive but ultimately still quite readable. I would prefer to see either of these over the original C code any day.

  • @artxiom

    @artxiom

    22 күн бұрын

    Short code can be good or bad and long code can be good or bad. You can write complicated long code but also very readable short code. If you can reduce long code into short code, while maintaining readability it will be always better. Not only does less lines mean there can be potentially less bugs but also it's faster and easier to read. You can understand what it is doing "on the spot" and don't have to scroll through a lot of code. A lot of code reduction is only about thinking declaratively and using FP functions like map() and reduce() efficiently. Unfortunately a lot of programmers are not taught these. I also learned it only after 10 years of programming...unfortunately, I wish I would have learned it way earlier.

  • @fabricehategekimana5350
    @fabricehategekimana5350 Жыл бұрын

    Super interesting video. I fell in love with rust for two reasons. Firstly because I wanted a language that can do low level code manipulation but a language that nicely implement functional programming (I tried haskell and the experience was lovely)

  • @dmitriidemenev5258

    @dmitriidemenev5258

    Жыл бұрын

    I also liked it for its reasonably good interop with other programming languages and because it promises to become even better!

  • @winniedobrokot
    @winniedobrokot Жыл бұрын

    int a2 = (a + 1)/2; int b2 = b/2; return (a2 + b2) * (b2 - a2 + 1); Also can be calculated as arithmetic progression sum without any filters :) Thanks for the great video, I used it as the opportunity to try the Rust

  • @helio6839

    @helio6839

    Жыл бұрын

    This was my first thought as well, although I don’t think the focus of the video is coming up with a more creative solution, but rather a refactoring/reformatting of an existing solution.

  • @noomade
    @noomade Жыл бұрын

    Haskell is just beautiful!

  • @logaandm
    @logaandm Жыл бұрын

    I don't consider myself a professional programmer, however, in my job as a physicist I have experience with numerical computation and programming with a focus on accuracy and speed. It was obvious that the original code was inefficient and this prompted me to comment and test before commenting. I assume the purpose of the example is to show how to modify code to use standard, safer, tested methods and to make the code more readable. Goals I am sure we all share. One of the bigger issues in programing, of course, are errors with unknow size of arrays. Not withstanding that there are far better ways to accomplish the same task as the C code, this particular code snip, however, is poorly chosen to illustrate the intended concepts. As pretty as the Rust and Haskell code are I remain unconvinced they are a significant worthwhile improvement. The modifications shown have all the hallmarks of using a sledge hammer to kill a fly. Adding even integers is trivial. Even the original C code shows that. Assume "low" is the lowest-even we want to include and "high" is the highest-even we want to include then: for(i=low;i

  • @tellur808

    @tellur808

    Жыл бұрын

    Your analytical solution, while very elegant, suffers from one problem: it also doesn't faithfully replicate the original I/O. What about negative inputs or mixed positive and negative inputs? Int is signed by default and negative inputs don't default to zero in the original code. You need to distinguish three cases, to make your approach work: 1. bottom & top > 0 stays the same (though I would use low = bottom - 2 + bottom % 2 as that automatically gets you the last positive even number below bottom and 0 is excluded) 2. Bottom ≤ 0, top > 0, needs their low adjusted to the nearest higher even number and negated: low = -(bottom + bottom % 2) this also covers the bottom = 0 case. 3. Top ≤ 0, bottom < 0, flip the signs and top/bottom to determine low/high, then multiply the sum by -1

  • @SpaceMonkeyTCT

    @SpaceMonkeyTCT

    Жыл бұрын

    I like your thinking about not altering the I/O of the function because bottom == top might need to return 0 and in making use of n(n + 1)/2, however, in doing so you have also changed the I/O because nowhere in the code does it check for negatives, which might be a valid use-case. Like you said, we'd need to know more about the original application. You are totally correct that readability has a cost, but after spending a few years working with code written by people with a different focus, readability is more than just nice, it is a godsend. If performance is a primary concern, I would suggest keeping the original code in the unit test as a reference and to compare to the optimised code to ensure the I/O has not been altered or to document how it has been altered. Getting back to the point of the original video, less indentation, we can re-write your code (not tested, probably has mistakes): int sumEvenIntRange(long int low, long int high) { // Method based on formula for sums of integers to n = (n*(n-1)/2) // If n is even, the sum of all even numbers up to n = ((n*n)+2n)/4 // This assumes low and high will both be positive, so: if (low return 0; } // this should be the second change everyone makes! (function name first) if (low>=high) { // Condition from original code doubted by some return 0; } high -= ((high%2 == 0)? 0: 1); // high-even to be included is either high if even or one less if high is odd highEvens = ((high*high)+(high2; // compilers probably optimise multiply/shifting // don't calc low sum if not required if (low

  • @logaandm

    @logaandm

    Жыл бұрын

    @@SpaceMonkeyTCT Your assumption is incorrect. I tested all the code. I did not however test for negative integer input as you point out. Honestly, I was just mentally lazy to check the math to see if it would work for negative numbers. It does. Modifying to replicate the original code for both positive and negative input the code is now simpler: int calculate ( long int low, long int high) { if(low

  • @SpaceMonkeyTCT

    @SpaceMonkeyTCT

    Жыл бұрын

    @@logaandm I was also too lazy to check the maths for negatives, assuming it only worked for positives, good to know it works negative too. I still stand by my point of readability when it comes to inverting the outer if to return early and even if you don't like ternary operators or shifting, I find them equally readable (which is not very) :)

  • @SpaceMonkeyTCT

    @SpaceMonkeyTCT

    Жыл бұрын

    @@logaandm I ran some tests and looked at the assembler. Calculating the low and high is basically the same using ifs and using ternary, except the high ternary reduces to high &= -2; a neat trick! It rewrites ((high*high)+(2*high)-(low*low)-(2*low))/4 into ((high*high)+(high+high)-(low*low)-(low+low))>>2, which made me think of rejigging the maths to use fewer operators so my current code is now: int sumIntRange(int low, int high) { if (high > 2; } Which is a tiny bit more performant but not readable.

  • @secretagent3712
    @secretagent3712 Жыл бұрын

    For C version of the program: How about not checking if(top > bottom). It should have been >= instead of >, anyway. Now, if top int calculate(int bottom, int top) { int i, sum = 0; for (i = bottom; i

  • @frydac

    @frydac

    Жыл бұрын

    C89 in 2022 :) it's been some time, I do think declaring the loop variable i in the for loop is objectively better. Also I don't think it is more readable to add zero, and I would expect the assembly to be the same if there was an 'if' statement, though could be wrong of course.

  • @secretagent3712

    @secretagent3712

    Жыл бұрын

    ​@@frydac I agree that it isn't more readable, but if the goal is to reduce nesting, this is one way to do it. As for the assembly code, I've never used assembly, so I can't comment on it. Although, it would be interesting to compare performance between different languages, as well as different code (like the one in my original comment).

  • @lesto12321

    @lesto12321

    Жыл бұрын

    Even worse than infinite loop, signed overflow is undefined.. here be dragons

  • @clawsie5543

    @clawsie5543

    Жыл бұрын

    There is even simpler way of doing this. Just round "bottom" to the next multiple of 2 and add every second number. Something like this: #define MOD(x, y) (((x) % (y) + (y)) % (y)) int calculate(int bottom, int top) { int sum = 0; for (bottom += MOD(bottom, 2); bottom

  • @secretagent3712

    @secretagent3712

    Жыл бұрын

    ​@@clawsie5543Yes, this is better. Define is probably unnecessary, though. It should be enough to write bottom += bottom % 2.

  • @tenthlegionstudios1343
    @tenthlegionstudios1343 Жыл бұрын

    Had a similar reaction to that same suggested youtube video. Love the content and comparisons between the languages!

  • @sagarramchandani3139
    @sagarramchandani31396 ай бұрын

    Just wanna comment that I am pleasantly surprised by how expressive rust looks like. I mainly work with Julia which is also very neat because the equivalent code there would be. calculate(bottom,top)=sum(filter(iseven,bottom:top)) Julia's type inference handles all typing in this case and also handles the (6,6) case you mentioned.

  • @oakley6889
    @oakley6889 Жыл бұрын

    So i got recommended and started watching CodeAesthetic and love his style and explaination. Now its suggested you, its one big circle

  • @christophbritsch1074
    @christophbritsch1074 Жыл бұрын

    I would have loved some benchmarks at the end. Like does the original version run faster? Do the std functions introduce unnecessary complexity or are they faster?

  • @HexenzirkelZuluhed
    @HexenzirkelZuluhed Жыл бұрын

    I've recently found more and more similarities in rust and python, actually. This is how I'd express it in Python, below. Replace top+1 in the range, depending on intent. I had the "Nevernester" Video in my recommendations, too. I still think he makes some good points, especially for beginners. def calculate(bottom: int, top: int) -> int: return sum(n for n in range(bottom, top) if n % 2 == 0)

  • @sheep4483

    @sheep4483

    Жыл бұрын

    this reminded me of an old code golf problem I solved, where I solved it something like this sum(range(bottom + bottom % 2, top + 1, 2))

  • @jimatperfromix2759

    @jimatperfromix2759

    Жыл бұрын

    Imagine that: Python has the most elegant solution.

  • @climatechangedoesntbargain9140

    @climatechangedoesntbargain9140

    Жыл бұрын

    i don't like the n for n in

  • @snippletrap

    @snippletrap

    9 ай бұрын

    @@climatechangedoesntbargain9140 how about sum(filter(lambda x: x % 2 == 0, range(bottom, top)))

  • @jaysistar2711
    @jaysistar2711 Жыл бұрын

    I had similar thoughts about that video. He did make it better, and I can't fault him for making content that is helpful for someone who wasn't initiated to functional style.

  • @BeansEnjoyer911
    @BeansEnjoyer911 Жыл бұрын

    Awesome! Rust and Haskell love! Also saw that Never Nesting video and was also unimpressed. Not only that he ended up creating an off by one error when he inverted a conditional statement

  • @jongeduard
    @jongeduard Жыл бұрын

    Currently learning Rust, so great to see such a video about it. Absolutely great programming language. This is after years of experience with several C family anguages for me, with C# as my daily one, which is wordt mentioning for it's functional programming (especially LINQ) as well. Doing your example in C# the code looks pretty nice as well. The only 2 downsides are that for the range we still need to call the Enumerable.Range method instead of using the two-dot way. This is because the Range type behind the two dots in C# has not yet implemented the iterator (Enumerator) pattern today. And we also need the ternary operator solution for top-more-than-bottom check. Luckilly C# has a Sum method, but otherwise the Aggregate method was still an option for the accumulation solution (reduce operation).

  • @helio6839
    @helio6839 Жыл бұрын

    I’m guessing the bug is that if top and bottom are equal, the c/c++ code returns zero, while the rust code actually runs the filter/sum combo on that single int. Edit: I was right

  • @gigachad8810
    @gigachad8810 Жыл бұрын

    awesome to see how rust can even rival python in its conciseness and readability from time to time

  • @sebastian6121

    @sebastian6121

    5 ай бұрын

    here have some gay ass posing as gigachad

  • @PhotonCompute
    @PhotonCompute8 ай бұрын

    Thank you, that was very interesting. I did not get involved in C++ back in the 90s because there were too many problems to make the transition from C which I had been using since the 70s, but now I can see that it is a time to take a fresh look at C++ and (more importantly) at Rust. Cheers.

  • @user-fh6vi7hz2b
    @user-fh6vi7hz2b Жыл бұрын

    Maybe someone in comments also spotted this bug in C code: if the top is equal to INT_MAX we will get an infinite loop cause after checking number

  • @AEF23C20

    @AEF23C20

    Жыл бұрын

    топ и боттом проверяются "где то" выше, зачем у вас неимоверное стремление проверить и перепроверить всё и вся, что перепроверять не следует? входные параметры в функцию никогда и ни за что не должны проверяться в самой функции, все эти проверки должны быть [как минимум], в вызывающем месте который вызывает эту функцию и даже кандишен (топ>боттом) вкрай идиотичен, потому что он должен быть опять и снова "где то" выше, т.е. main() { иф(топ>боттом) кэлькулейт(боттом топ) } и даже это идиотично, ну потому что на самом деле проверка (топ>боттом) _уже_ где то _существует_, ессно на этапе создания структур например, именно там она должна быть а вы как обычно "стремитесь" к массовой идиотии, и проверяете всё и везде, однако же идиотия на то и идиотия, ну потому что полностью лишена логики в итоге все ваши идиотские проверки проверок от проверок над проверками только лишь выжирают батарейки и атомные электростанции, и толку с этого абсолютно нет, это банальное вредительство

  • @AEF23C20

    @AEF23C20

    Жыл бұрын

    а что бы функция не выкидывала переполнение, допишите к функции банальный комментарий, когда и при каких условиях функция будет валиться

  • @p39483

    @p39483

    Жыл бұрын

    Inclusive ranges: Just don't.

  • @Arturo-Peredo
    @Arturo-Peredo Жыл бұрын

    I feel the C code itself could have some improvements: int calculate(int bottom, int top) { if (top > bottom) { int sum = 0; if (bottom & 1 != 0) bottom++; for (bottom; bottom

  • @MrZzzjjj

    @MrZzzjjj

    9 ай бұрын

    good refactoring. A further improvement can be: int calculate(int bottom, int top) { if (top

  • @DanelonNicolas
    @DanelonNicolas Жыл бұрын

    Ok. you got me. I just love this video! Wonderful to learn that rust improvement

  • @dwarftoad
    @dwarftoad Жыл бұрын

    Note that since sum is commutative (and associative) you could use std::reduce in C++ instead of accumulate and use one of the parallel execution policies, if so desired. However the optimizer can also automatically vectorize loops sometimes as well, especially dealing with integral types and clear operations like +, so it is probablydoing that for the C code or the loop based C++ code and maybe the ranges one too, depending on the specific compiler etc.

  • @ExodiumTM
    @ExodiumTM Жыл бұрын

    Man I'm still learning basic C stuff and that last C++ code is just ☠️☠️☠️

  • @Ogrodnik95

    @Ogrodnik95

    Жыл бұрын

    im dev for years in cpp and it indeed is ☠☠☠ even for me. you dont use such things in code that many developers see and read every so often as to not confuse them. when writing code you try to write it in a way, that even dumbest but decently qualified dev can understand it. also names of variables and function arent what you would want to leave in source code. also, when it comes to extracting parts of code to separate functions - it is quite controversial - in my workplace we dont usually care enought to reduce function volume more as it is not that big yet and is decently uderstandable in current form. also, we dont really want to jump too much around the code to check each function due to size of project.

  • @not_ever

    @not_ever

    Жыл бұрын

    @@Ogrodnik95 You don't see this code in production but are you using C++ 20 or 23 yet*? Maybe this is a future we have to look forward to. * I agree with what you've written btw, this question is not a challenge to what you said.

  • @Ogrodnik95

    @Ogrodnik95

    Жыл бұрын

    @@not_ever we 'just' started using cpp17 :D

  • @rad6626
    @rad6626 Жыл бұрын

    Me watching this guy "refactor" nice and readable code into the most monstrous spaghetti code I've ever seen

  • @spacelem
    @spacelem Жыл бұрын

    I saw the same video, and I was also disappointed. It's been a few years since I wrote anything in C++, and I'm glad to that it's getting better at FP, as whether I'm coding in R (which hates loops), or in Julia (which is just lovely), it's a style that's a lot more pleasant to work with.

  • @Bbdu75yg
    @Bbdu75yg Жыл бұрын

    Damn ,The haskell code looks so good

  • @SpudMackenzie
    @SpudMackenzie Жыл бұрын

    This kind of refactor feels like such a revelation after watching all your APL videos. That whole thinking with algorithms thing.

  • @glaux102
    @glaux102 Жыл бұрын

    this is the senior content i was looking for

  • @ar1i_k
    @ar1i_k Жыл бұрын

    The entire video I was waiting for you to change the C example by replacing "number++" with "number+=2" and reduce O(n) "even" comparisons to O(1) (only first number). The final C++ example made me want to scream. At least in Rust the same thing looks nicer

  • @drstkova
    @drstkova Жыл бұрын

    I understood the original C and it was easy to spot any bugs. As soon as you made C++20 substitutions I thought “what the hell is that?” and the code looked like illogical gibberish. In the commentary you then said “I think this is a lot nicer”! From my perspective you made simple, legible, code totally impenetrable to the point where I’d need to use tools to find bugs in it. I programmed commercial products in C in 1996 and C++ in 1998. I’m trying to figure out whether it’s worth learning this whole new syntax/toolbox that modern C++ requires- in this case it obfuscated the code.

  • @markus4925

    @markus4925

    Жыл бұрын

    I agree.

  • @Zipperheaddttl

    @Zipperheaddttl

    Жыл бұрын

    Its not. I program commercial products today (games) and I write code like you did in 1996.

  • @peezieforestem5078

    @peezieforestem5078

    Жыл бұрын

    not only is this not worth it, you might end up getting trapped in the same sunken cost fallacy that so many developers do, where they've wasted a bunch of time learning things that don't really improve all that much, and so not they have to lie to themselves about how the code looks nicer and smarter, and how everyone who didn't sink as much time as them learning useless things is just too stupid to get it.

  • @alvarohigino

    @alvarohigino

    Жыл бұрын

    But that's C++ nowadays, a language that provides 1 million ways to do something. That's why we are seeing a lot of new languages trying to conquer its place, bcs nobody wants the new C++.

  • @chanky1000
    @chanky1000 Жыл бұрын

    I read the last histogram to mean that the simplest no-nonsense C with the O2 flag is way more efficient than all the funky new-age stuff that came later

  • @professorgvd
    @professorgvd Жыл бұрын

    I'm sure this is overly pedantic but the `iota(start, end + 1)` feels bad when `closed_iota(start, end)` exists.

  • @code_report

    @code_report

    Жыл бұрын

    I actually didn't know about closed_iota. However, it only exists in range-v3, not C++20 or 23 ranges. That being said, I did start using range-v3 when I introduced ranges::accumulate so I could have added it then. Thanks for putting it on my radar.

  • @simmons3944
    @simmons3944 Жыл бұрын

    how did you create the animation bewteen slides? looks great

  • @code_report

    @code_report

    Жыл бұрын

    I have a follow up video on this in a couple days 🙂

  • @CostaKazistov

    @CostaKazistov

    Жыл бұрын

    PowerPoint maybe

  • @cueto303
    @cueto303 Жыл бұрын

    Great job! just a question, how do you measure the amount of assembly instructions generated by your code?, thanks in advance.

  • @dwarftoad
    @dwarftoad Жыл бұрын

    Just looking at number of instruction generated is not always useful (unless you're trying to fit the code on a tiny PIC or something): first, the optimizer will try to inline functions and unroll loops (more in -O3 than -O2) which is great because inlining (and unrolling to some extent) makes a bunch of other optimizations possible, and in addition, in C++ you will get alternate code paths generated away from the normal code (kind of like having a separate, alternate function not next to the "hot path" of instructions in memory) for exception handling because they are expected to be unlikely but still possible; but the actual time (or instructions executed) in the case of no exceptions thrown will still be pretty small. Also tip when trying to look at the assembly code in Compiler Explorer to judge your code: use argc or argv or console input or random numbers or similar as dependent values (inputs) of the example code, otherwise the compiler/optimizer will just evaluate the code at compile time and the resulting program is actually just spitting out the constant results (even if the code for functions etc. is still there in the binary.)

  • @anon_y_mousse

    @anon_y_mousse

    Жыл бұрын

    Can confirm, at -O3 I've seen entire test suites reduced to printf( "%d ", result ); // though I did it intentionally, it was still funny to see.

  • @Pacanata
    @Pacanata Жыл бұрын

    Superb. I so enjoyed this video. Gracias!

  • @DavidAlsh
    @DavidAlsh Жыл бұрын

    Cool video, thanks for sharing. It's an interesting discussion; the transfer from imperative to declarative programming styles. As you mention in your video, the declarative syntax is less overwhelming once you become familiar with the tools available to you and that's where my biggest criticism of it lies. I have found that declarative code tends to have a negative impact on maintainability. The inability to use skills learned from other languages requires contributors to have knowledge of language-specific utilities, thereby increasing the barrier of entry and reducing the pool of viable contributors or increasing the time it takes for individuals to be productive. The declarative aspects of C++ are different to that of Rust, to that of Haskel, to that of JavaScript - but an "if" statement is an "if" statement everywhere you go. In my experience, boring and obvious code makes for maintainable and approachable code. While I, as a hobbyist, love tricky fancy code - it really sucks in a project setting.

  • @hemmper
    @hemmper Жыл бұрын

    The best way to "never nest" this is to use a much faster O(1) algorithm instead of the O(n) ones presented: int calc(int b, int t){ b = ++b>>11

  • @anon_y_mousse

    @anon_y_mousse

    Жыл бұрын

    Best version I've seen yet that matches the output of the original. I like it, even if I think the functionality of outputting 0 when the range is passed in the wrong order is wrong behavior. Even correctly handles negative numbers.

  • @gigacool30
    @gigacool30 Жыл бұрын

    How to turn clean code to unreadable mess

  • @formikdev9270
    @formikdev9270 Жыл бұрын

    what font was used for this video? I really like it and id like to start coding with it

  • @TheItamarp
    @TheItamarp Жыл бұрын

    A "friendlier" option to the ternary operator which is going to be more readable for some people is to check the reverse of the if statement first, and "exit early", placing the evens sum logic after the if block. This gets rid of the need for the else block and leads to an almost entirely flat function...

  • @HarshVerma-oz5uo
    @HarshVerma-oz5uo Жыл бұрын

    Does this make the code execution faster or is it just about how fancy code can look?

  • @KohuGaly

    @KohuGaly

    Жыл бұрын

    I would be honestly surprised if there was any meaningful difference in performance, especially at high optimization levels. I'm actually surprised it even produces different assembly at all.

  • @VimCommando
    @VimCommando Жыл бұрын

    Having spent some time programming Javascript and Ruby, starting in high school with C and Pascal, I always though “Rust is a high level language” was an odd statement. But after seeing that C++ comparison, now I get it 😂

  • @emilien.breton
    @emilien.breton Жыл бұрын

    "I saw it first!" I was also disappointed and somewhat annoyed when I watched the original video. I'm glad you made this video to show what a proper refactor can look like.

  • @muha0644
    @muha064410 ай бұрын

    my spin on this problem: ```int calculate(int bottom, int top){ int sum = 0; bottom += bottom%2; while(bottom

  • @TomHultonHarrop
    @TomHultonHarrop Жыл бұрын

    One thing I didn't see mentioned in the video or in the comments so far is the matter of compile times. I did some quick tests locally using the 'time' utility on macOS, timing compilation of each version. Unfortunately compile times get gradually slower each time. The initial C and reformatted C++ version take approximately 0.06s to compile (M1 Macbook Pro, Ninja build), but by the time we get to the range-v3 accumulate (ternary operator) version, the code takes approximately 0.8s to compile. This means the original version compiles 13x faster than the rangified version (an order of magnitude). It's tough as I do really quite like the more declarative approach of the final code, but the cost (when magnified across an entire code base) is prohibitively high at the moment.

  • @Tabu11211
    @Tabu11211 Жыл бұрын

    I love it when I find a random video that replies to another random video I watched. I missed the old KZread algorithm when I could see things that I had never seen before. this kind of reminds me of that

  • @starostka
    @starostka Жыл бұрын

    Great content! I’m curious, how do you make these code transitions? It’s a great way to visualize and explain the ways of implementation. ☺️

  • @starostka

    @starostka

    Жыл бұрын

    Nvm.. He had a video explaining it 😅

  • @RogueShadowTCN
    @RogueShadowTCN Жыл бұрын

    I was never able to get into c/c++ but now I really enjoy rust. Rust is great, pretty, expressive and straightforward. I remember having much difficulty in c++ finding the "right" way to do the simplest things... And it was uglier the nicer the feature was ....

  • @tuluppampam
    @tuluppampam Жыл бұрын

    In case anyone missed it, and apparently many did, the idea of the original C code was to have some actually functional code to show how to reduce nesting It was not meant to be the best way of implementing the operation (it isn't) It was not meant to be perfect (it isn't) It also isn't the fastest, nor the prettiest, nor anything else It is a good example for what it is meant to be It was meant to give an example that can be abstracted to other situations (something it accomplished very well) Go watch the original video if you actually care about what it originally meant, but if you wanna whine about its imperfections, go on

  • @tordjarv3802
    @tordjarv3802 Жыл бұрын

    I would be embarrassed to see either of those in my code, and so would Gauss. Here is what I would do (Rust version): fn calculate(bottom: i32, top: i32) -> i32 { (top/2 + bottom/2)*(top/2 - bottom/2 + 1) } Infact, I'm pretty sure that some C and C++ compilers (clang) would recognize the pure for-loop versions as the sum of all even numbers between bottom and top and replace it with the very formula I used and thus turning an O(bottom-top) function in to a O(1) function. However, when using all the "zero-cost abstractions" this would not be the case. Also, as someone that is trained from childhood with function composition being from left to right and not right to left I find the Rust version to be backwards (the Haskell version is alright).

  • @peezieforestem5078

    @peezieforestem5078

    Жыл бұрын

    I do believe that the code is not meant to be taken literally, e.g. you might want to edit conditions and values later, it's just an example code, hence why the function is called "calculate" and not "sum_of_all_even_numbers". But yes, you're correct that this particular version is solved in a const time with a simple formula.

  • @tordjarv3802

    @tordjarv3802

    Жыл бұрын

    @@peezieforestem5078 I know that it is an specific example. However, you seem to miss my point, that by using all those extra levels of abstractions, both the programmer and the compiler might miss trivial optimizations.

  • @peezieforestem5078

    @peezieforestem5078

    Жыл бұрын

    @@tordjarv3802 I see your point, but you assume optimization criteria. Let's say we optimize for minimum code alteration for likely changing requirements while also maintaining minimal code size. Now, the solution you propose is not optimal, nevermind trivially optimal. Had you known in advance that the problem will always stay this exact way, you would be correct. But you don't, in fact, depending on your environment, you can be 90% certain that at some point your customer will barge in and tell you to redo everything. In this case, you optimizing for specifics of the problem is waste in the meta-sense, unless you wish to challenge yourself.

  • @tordjarv3802

    @tordjarv3802

    Жыл бұрын

    @@peezieforestem5078 If the customer demands to redo everything, it will not matter how the code looks (because you have to redo everything, or maybe you don't agree what "everything" means).

  • @tordjarv3802

    @tordjarv3802

    8 ай бұрын

    @@anserinus no those two are not the same, because we are talking about integer division. for example let top=5 and bottom=3 then (5/2 + 3/2)*(5/2-3/2+1)=(2 + 1)*(2 - 1 + 1)=6, while (5+3)*(5-3+2)/4 = 8.

  • @AndyQuinteroM
    @AndyQuinteroM Жыл бұрын

    It's uncanny how we get such similar youtube recomendations

  • @borisbeginin
    @borisbeginin Жыл бұрын

    Hey man great video! Really impressive c++ knowledge. However, it think the point of the original video was not about some particular function but more like an idea that the more branches it has the more bugs you will appear on average

  • @salman8562
    @salman8562 Жыл бұрын

    What formatter do you use for the c++?

  • @jeancerrien3016
    @jeancerrien3016 Жыл бұрын

    Will all your examples behave the same if top is smaller than bottom?

  • @void_p
    @void_p Жыл бұрын

    wow I was looking for something like this, thanks!

  • @lingdocs
    @lingdocs Жыл бұрын

    Great video! Do you mind sharing what software you use to make the video? And how did you get the nice transitions with the text moving around on refactors? Keynote magic move?

  • @code_report

    @code_report

    Жыл бұрын

    kzread.info/dash/bejne/iJxn25OenMSTj9Y.html

  • @lingdocs

    @lingdocs

    Жыл бұрын

    @@code_report Thanks, great! Just saw that. The morph transition with words in PPT is really, really nice.

  • @frydac
    @frydac Жыл бұрын

    I prefer a guard clause over if/else or ternary in this case. I think it improves readability.

  • @gideonunger7284

    @gideonunger7284

    Жыл бұрын

    well im glad you arent my coworker then

  • @Muttisuri
    @Muttisuri Жыл бұрын

    Small note, due to Haskell's powerful type system, the first line of the calculate example is an optional type signature. Haskell can actually infer quite a lot based on what functions you use. The more general type that Haskell infers is "calculate :: Integral a => a -> a -> a" Integral includes stuff like Integer and Word (a byte). So basically any form of an integer number.

  • @bzboii
    @bzboii Жыл бұрын

    been loving the podcast rust content also that prob influenced this rabbit hole lol

  • @YuriNiitsuma
    @YuriNiitsuma Жыл бұрын

    Conversa de bar de uma função em código... TOP DEMAIS

  • @NithinJune
    @NithinJune4 ай бұрын

    i completely agree with you that the final version of the cpp code is more declarative and i like it

  • @duttaoindril
    @duttaoindril Жыл бұрын

    I think you missed the point of the Code Aesthetic Video - it was more about control flow than functional programming and algorithms. The other examples he had, where it was more business logic and things you can't simply reduce into better functional mathematical expressions, are where his tips are needed to have a more readable and maintainable codebase.

  • @watynecc3309
    @watynecc3309 Жыл бұрын

    CodeAesthetic is amazing

  • @VictorMistral
    @VictorMistral Жыл бұрын

    For the assembly count, generaly smaller is faster, but not always, some asm instruction especially in CISC can be slower then other, (or faster). So if code path finds a way to use AVX it's probably be faster then one that use "jump" for the loop. And it's also possible that for some reason, one compiler targets more modern version of ix86 then another, or one compiler target different instruction, and add a runtime switch to select the best instruction set based of what is supported by the processor. O3 tends to favor speed over size, it probably unrolled the loop as much as it could to minimize the ammount of jump instruction that happened, and probably made all the jump as close as it could if it was all in a signe module to increase cache coherence of any jump along the hot path to avoid having to hit memory, and could thus be way bigger, and hopefully faster... So instruction count is "decent" metric, but far from enough... It's better if you target a specific RISC cpu, so cross-compiling everything a specific ARM version, makes instruction count more closely related to perf, in my experience...

  • @JosephSalmans
    @JosephSalmans Жыл бұрын

    I did not see any bug in the code. if the top is not greater than the bottom return 0. pretty clear what it was meant to do. If I had never seen a line of C code I could still figure it out. whether or not you wanted it to return the value if the range is length 0 is entirely up to the programmer. the only time i value abstraction is if I don't care about the code only what it returns. I like seeing things like this. conn = database.connect("database"). that is acceptable abstraction to me. if I am diving into the logic of a function, please make it clear about what it does don't abstract it with more functions i have to investigate. what would happen if I wanted it to return 0 if the input range was 0? I would probably end up rewriting the original function to something more understandable that doesn't use library calls.

  • @maxverb
    @maxverb Жыл бұрын

    Curious about the instruction count if C++ were compiled with Clang (an LLVM compiler), if it would be more similar to the rust output (also LLVM).

  • @57d

    @57d

    Жыл бұрын

    Clang 16.0.0 -O3 generates 45 lines, as opposed to Rust at 50.

  • @mettemafiamutter5384
    @mettemafiamutter5384 Жыл бұрын

    I analysed the assembly code. At -O2 the C code has the tightest assembly and at -O3 the C code is auto vectorized. The C++ version cannot be auto vectorized and the scalar code that is generated at -O3 is H O R R I B L E compared to the C code at -O2. I wrote the scalar assembly by hand and compared it to GCC and I managed to shave off one instruction but that was it.

  • @abauchu
    @abauchu Жыл бұрын

    What about performance? Both for compiling and executing? I have serious doubts about the cpp version

  • @Bondrewd_21
    @Bondrewd_21 Жыл бұрын

    Congratulations, you just reinvented FP in C++

  • @mert_2577
    @mert_2577 Жыл бұрын

    Honestly, looking at the C++ part, I can't really think who would write code like that. You don't need to use every standard library function or have a lambda for a command as simple as "return e % 2 == 0" since you use it once. I think the reformatting stage was more than enough because the rest is just overengineering at that point.

  • @centis4533
    @centis4533 Жыл бұрын

    Hi, Could you please make a video on running the latest features of C++ like Executors? Since these are not completely there in standard library, how to take the code examples & run. There is nothing much available in internet.

  • @DevlogBill
    @DevlogBill Жыл бұрын

    Hi code_report, I would like to try out a functional programming language. I am still fairly new to programming. Almost 2 years of programming in JavaScript now Kotlin. I have tried out C and C++. What functional programming language would you recommend to someone who is still fairly new to programming?

  • @code_report

    @code_report

    Жыл бұрын

    Haskell 😊

  • @DevlogBill

    @DevlogBill

    Жыл бұрын

    @@code_report Thanks, I wonder what editor or IDE I can run this on?

  • @user-sd4iq7no8s
    @user-sd4iq7no8s6 ай бұрын

    You can write Haskell version as [bottom .. top] & filter even & sum to resemble other versions more

  • @danielmilyutin9914
    @danielmilyutin9914 Жыл бұрын

    Iterators in C++ and Rust are implemented in different manner. Unfortunately, filter in C++ ranges has to evaluate predicate twice. There is a library called "pipes" by JoBoccara and it solves this issue by attaching consuming pipe to range instead of producing range. Or there is experimental 'cache1' view in ranges which stores last value, as far as I remember. And I'd agree I like Rust code here quite more. But I still love C++. 😁

  • @sarqf212
    @sarqf212 Жыл бұрын

    Still wishing to learn how you animate your videos and presentations! 🙂

  • @code_report

    @code_report

    Жыл бұрын

    I am releasing a "How to Make Beautiful Code Presentations" video tomorrow that will show the behind the scenes of how I made this video.

  • @chathamabate
    @chathamabate Жыл бұрын

    I may be wrong here, but is instruction count alone an accurate measure of optimization? At first glance, I would assume the C code would run the fastest as it is closest to machine code. Whereas the C++ code uses std library function calls. Will the C++ std library calls in this video be translated to the same machine code as the original C for loop? My first instinct is no, but I don't know for sure. It would be cool if you made a follow up video comparing the actual assembly instructions and runtimes of each program.

  • @devnull1013

    @devnull1013

    Жыл бұрын

    There are no "std library function calls" here. Those algorithms are template functions which get instantiated and turned into simple inline loops at compile time.

  • @michaelmueller9635
    @michaelmueller9635 Жыл бұрын

    BEST THUMBNAIL EVER I always post in comments, that Rust is crossover of C/XX + Haskell + programmer experience of severe bugs. If you understand C/XX and it's struggles and pitfalls. If you understand Haskell and it's struggles and pitfalls. Then you understand why Rust is done the way, how it is designed to.

  • @jenreiss3107
    @jenreiss3107 Жыл бұрын

    I came from Haskell to Rust and I love it

  • @MisererePart

    @MisererePart

    Жыл бұрын

    Even as Rust developer i must agree Haskell solution is quite elegant here.

  • @jenreiss3107

    @jenreiss3107

    Жыл бұрын

    @@MisererePart Haskell will be that way right up until you need to optimize. The gap between readable and optimized code in Haskell is probably larger than in any other programming language

  • @mskiptr

    @mskiptr

    Жыл бұрын

    @@jenreiss3107 Well, you can optimize code with rewrite rules and other stuff like that…

  • @teclab2265
    @teclab2265 Жыл бұрын

    I'm only on 1:36 and the entitlement is off the chart.. "Is not what I wanted to see.." ohh boy..

  • @tylerdback2025
    @tylerdback2025 Жыл бұрын

    Very elegant code! Here's another reformat using the Common Lisp loop macro: (defun calculate (bottom top) (loop for x from bottom to top when (evenp x) sum x))

  • @pepkin88
    @pepkin88 Жыл бұрын

    I think there is some misunderstanding at your part regarding to what CodeAesthetic's video was meant to present. You said that you expected a different refactorization of the code, to essentially move more towards the functional style. But it was not the topic of his video. The video was about nesting and showed how you could denest your own code by providing a code snippet, that is easily understood by a large audience, also by users of different programming languages. What the code actually does was not the topic of the video. It was just an example, a tool to show a couple of methods for denesting. It shows, among other things, the guard pattern. Your video is about a different thing. Your video shows how to refactor the code to be more functional, and therefore shorter, more readable, and thus more bug-resilient. The resulting code is indeed denested, but your video doesn't teach much in terms of denesting, which was a topic of the CodeAestethic's video. You said, that you were disappointed, because you were hoping that his video would go in the different direction in regards to refactoring this code fragment. Later you show, how you would refactor it. That suggests, that you would expect a similar refactorization in his video. I think the video would lose by doing that. Even if your way of refactoring of this specific code piece is better, it's worse in the context of his video. You could argue, that he could choose a different example, but I think he did a good enough job, because the example was easy to understand, and was a good material to present some of the denesting techniques. Cheers!

  • @rutabega306

    @rutabega306

    Жыл бұрын

    Yeah idk why this video started off like that. It's a good video, but no reason to say that he was disappointed by CodeAesthetic's video. CodeAesthetic presented a very useful (and language agnostic) coding concept in a nice way!

  • @gardendado1999
    @gardendado1999 Жыл бұрын

    the datatype, we either need to limit the maximum sum of "sum" to an int32 or make "sum" > int32, int64/long etc

  • @eternalsnows6071
    @eternalsnows60715 ай бұрын

    I was testing out the C++ refactor(s) and I can't get either 5:03 or 5:40 to work. The first returns the wrong value and the second throws an error about ranges::accumulate being overloaded or something. I installed ranges-v3 via vcpkg. VS 2022 using C++ 20 standard. Any ideas what might be wrong?

  • @JoshuaSendall
    @JoshuaSendall Жыл бұрын

    I took a look at compiler explorer with GCC. The saddest thing that I saw with the c/c++ code is that the compiler never realized that it can test 1 element and then just do the sum, incrementing by 2 each time. I wonder if the Rust compiler could do better.

  • @hareTom

    @hareTom

    Жыл бұрын

    Isn’t rustc uses llvm to optimize? So the optimization passes is the same in c++ when using clang++ to compile