Why did rust change established loop patterns??

Why did rust change established loop patterns?

// c++
for (int i {1}; i <= 99; i += 2)
for (int i {99}; i > 0; --i)
for (int i {100}; i > 0; i /= 2)

// rust
for i in (1..=99).step_by(2)

let mut i = 99;
while i > 0 {
i -= 1;
}

let mut i = 100;
while i > 0 {
println!("{}", i);
i /= 2;
}

Thalidomide Vintage Ad Shirt $22.14

Ape Out Shirt $21.68

Thalidomide Vintage Ad Shirt $22.14

  1. 1 month ago
    Anonymous

    >for (int i {100}; i > 0; i /= 2)
    >int i {100}
    Why did c++ change it?

    • 1 month ago
      Anonymous

      >https://en.cppreference.com/w/cpp/language/initialization
      >std::string s3 = "hello"; // copy-initialization
      >std::string s4("hello"); // direct-initialization

      >https://en.cppreference.com/w/cpp/language/direct_initialization
      >Direct-initialization is more permissive than copy-initialization: copy-initialization only considers non-explicit constructors and non-explicit user-defined conversion functions, while direct-initialization considers all constructors and all user-defined conversion functions.

      Basically in OP's example there is no reason to do it like that and he could have used the copy initialization like used in C.

      • 1 month ago
        Anonymous

        God I hate C++ so fricking much.

        • 1 month ago
          Anonymous

          No matter how much you hate C++, you don't hate it enough.

      • 1 month ago
        Anonymous

        Why doesn't compiler just optimize it away? Why two different syntaxes?

        • 1 month ago
          Anonymous

          Like most of the bullshit in C++: retro-compatibility.
          Some old code might rely on a side effect of the constructor being called twice in copy-initialization.

      • 1 month ago
        Anonymous

        So morons heard "no copy initialization" and they started thinking this shit applies to fricking primitive types and now we get this nasty code? Damn, brainlets really struggling to learn C++ and writing obscure code since day one, nice.

        • 1 month ago
          Anonymous

          no you gigabrainlet, it is used in loops to match the style of the codebase where you use brace init everywhere.

  2. 1 month ago
    Anonymous

    loops are basically a code smell. We prefer iteration with higher order functions ie map, filter, reduce etc.
    I do the same thing in JS too except in rust it’s cost free abstraction.

    • 1 month ago
      Anonymous

      >2024
      >loops are... la bad

      • 1 month ago
        Anonymous

        Yes, whenever I see a loop, I just know it’s written by a brainlet who got filtered by HOF, or his shitlang doesn’t support it.

        • 1 month ago
          Anonymous

          >HOF
          The problem with that is people will say that and then you benchmark the performance and most of the time the loop performs better.

          • 1 month ago
            Anonymous

            That's just C++ issue.

          • 1 month ago
            Anonymous

            In most languages this holds true. I haven't tested for rust, but after a while you start to realize that you are trading performance for style which is never worth it.

          • 1 month ago
            Anonymous

            Rust is pretty good in optimizing away functional style code. Especially in iterators, which can be even faster than hand rolled solution(on safe subset).

          • 1 month ago
            Anonymous

            >safe subset
            Does that just mean it in an unsafe block? Also wouldn't this create this annoyance where you have to drop your functional style in unsafe blocks to maintain performance?

            Simple cases optimize well IME, aggressive inlining and monomorphization is enough to make it equivalent to or even better than manual loops. For more complicated patterns it's mixed, sometimes it works out and sometimes it doesn't.
            Rust iterator chains can be extremely easy to parallelize with rayon, that's a bonus.

            >better than regular loops
            I find this surprising. Do you have a source on how that works or is it just rust source?

          • 1 month ago
            Anonymous

            >I find this surprising. Do you have a source on how that works or is it just rust source?
            It's a mix, and not extreme.
            Most recently I got a 30% speedup in a tight loop where I'm pretty sure it just happened to nudge the optimizer into a different direction that worked better. There was no obvious reason to get different assembly output at all.
            Rust has bounds checking on indexing, while iterators tend to be in-bounds by construction. In practice LLVM is really good at noticing invariants and optimizing out the bounds checks in manual loops but there probably exist cases where this elision fails and it's possible to do better with an iterator. (I think this is what the other poster was focusing on but IMO it's often exaggerated.)
            The standard library has a few clever specializations. Take this code:
            fn to_abs(nums: Vec<i32>) -> Vec<u32> {
            nums.into_iter().map(i32::unsigned_abs).collect()
            }
            It receives a vector of signed integers by value and outputs a vector of unsigned integers.
            The standard library is smart enough to reuse the allocation, even though the input and output types are different. That would be nasty to do manually but here it happens automatically. (It can be a footgun though, especially if the output type is smaller than the input type or if you remove elements. The allocation might stay much larger than needed and waste memory until you call shrink_to_fit().)
            >Does that just mean it in an unsafe block?
            Kinda, but mind that unsafe blocks don't do anything by themselves, they give you access to features and APIs that you don't otherwise have. For example if you want to skip bounds checks you get to call arr.get_unchecked(i) instead of using arr[i]. And you get to dereference raw pointers, which otherwise gives a compiler error.
            >Also wouldn't this create this annoyance where you have to drop your functional style in unsafe blocks to maintain performance?
            I mix functional and imperative style all the time even in safe code.

          • 1 month ago
            Anonymous

            >The standard library is smart enough to reuse the allocation, even though the input and output types are different.
            Uh, that's pretty cool, now I have to wonder how I'd implement that in C++.

          • 1 month ago
            Anonymous

            >Does that just mean it in an unsafe block? Also wouldn't this create this annoyance where you have to drop your functional style in unsafe blocks to maintain performance?
            No. Functional style can allow compiler to optimize away some checks that would otherwise add an overhead if you wrote them imperatively without unsafe.

          • 1 month ago
            Anonymous

            Simple cases optimize well IME, aggressive inlining and monomorphization is enough to make it equivalent to or even better than manual loops. For more complicated patterns it's mixed, sometimes it works out and sometimes it doesn't.
            Rust iterator chains can be extremely easy to parallelize with rayon, that's a bonus.

        • 1 month ago
          Anonymous

          >Yes, whenever I see a loop, I just know it’s written by a brainlet who got filtered by HOF, or his shitlang doesn’t support it.
          how would you draw a line on the screen from x1,y1 to x2,y2?
          no libraries (you have 2d array for the framebuffer)

      • 1 month ago
        Anonymous

        is that black ops guy?

        • 1 month ago
          Anonymous

          that sounds a bit racist

    • 1 month ago
      Anonymous

      please be trolling

      • 1 month ago
        Anonymous

        Loops imply boundary checks and it is therefore memory unsafe. Only obsolete languages like C use this anti-patterns. So my advice is don’t listen to anything cniles try to sell you.

        • 1 month ago
          Anonymous

          More precisely, index-based loops.
          Range based for loops are perfectly fine and have the same performance when you turn on source hardening.

    • 1 month ago
      Anonymous

      Damn, this is pretty sweet. How can sepples even compete?
      https://godbolt.org/z/3xd84GcK1

      • 1 month ago
        Anonymous

        Use sum(): https://godbolt.org/z/oxjaMaKx3
        Or if that's too abstract you can provide an initial value and get the same assembly: https://godbolt.org/z/b6eWM4PGz

      • 1 month ago
        Anonymous

        Use sum(): https://godbolt.org/z/oxjaMaKx3
        Or if that's too abstract you can provide an initial value and get the same assembly: https://godbolt.org/z/b6eWM4PGz

        Shouldn't you put an if condition to handle 0, 1 and negative values in the range generator? Or did misunderstood the code?

        • 1 month ago
          Anonymous

          num is unsigned so negative values are impossible.
          The behavior for 1 seems OK. That's an empty range.
          You might want to handle 0, yeah. Right now it also treats that as an empty range but you could panic or return an error or something.

      • 1 month ago
        Anonymous

        C++ has it in the form of range view adaptors, except
        - the syntax is shit
        - the specification is fricked up so range view pipe composition algorithms with filters do not vectorize at all

      • 1 month ago
        Anonymous

        Skill issue.

    • 1 month ago
      Anonymous

      this man is coming to your house to kill you
      you have ten seconds
      and yes, he will be wearing the silly goggles

      • 1 month ago
        Anonymous

        Rob pike has gone senile.

        • 1 month ago
          Anonymous

          rob pike has gone based
          https://github.com/robpike/filter
          >I wanted to see how hard it was to implement this sort of thing in Go, with as nice an API as I could manage. It wasn't hard.
          >Having written it a couple of years ago, I haven't had occasion to use it once. Instead, I just use "for" loops.
          >You shouldn't use it either.

          • 1 month ago
            Anonymous

            >https://github.com/robpike/filter
            What the moron doesn't realize is that the filter function is meant to be chainable on iterators. In brainletspeak:
            it's slice.iter().filter().map().collect(), not collect(map(filter(iter(slice*~~)

          • 1 month ago
            Anonymous

            right is how python does it because based moron guido

          • 1 month ago
            Anonymous

            >right is how python does it
            Python is also moronic.

            not possible in go (not that it matters, his point still stands)

            >not possible in go
            Yeah that's why he's coping.

          • 1 month ago
            Anonymous

            you're coping because you have to spend your time being productive instead of code golfing
            you COULD extend the language with a dedicated iterator type, or allow []any as a receiver type, or do some other stupid shit, but that's not going to happen because go moves slowly and carefully considers changes before adding them as a permanent part of the compatibility contract

          • 1 month ago
            Anonymous

            >I'm not coping YOURE coping
            lmao ok, keep(coping(homosexual(*~~

          • 1 month ago
            Anonymous

            not possible in go (not that it matters, his point still stands)

    • 1 month ago
      Anonymous

      >I want it to be slightly harder to read and also run slower because it makes my epeen bigger

      • 1 month ago
        Anonymous

        >slow
        It's faster. See

        Skill issue.

      • 1 month ago
        Anonymous

        HOF is easier to read. They are abstraction for humans and they express the intent clearly. For loops are easy for only the machine.

  3. 1 month ago
    Anonymous

    For counting down I do for i in (1..=99).rev().
    For halving I'm fine with writing out a while loop.
    Traditional for loops only let you specify a start and an end and a step. Modern for loops tend to use iterators. The style of for loop you're used to is just one way to do it and it's never been universally adopted.

  4. 1 month ago
    Anonymous

    >let mut i = 99;
    >while i > 0 {
    > i -= 1;
    >}
    OP is stupid. This is just
    for i in (1 .. 100).rev()

    >bbbbb-but /= 2
    for i in (0 ..).map_while(|n| NonZeroUsize::new(100 >> n))

    You dont know what a slice is
    You dont know what a pattern is
    You dont know what a proc macro is
    You dont know what a first class tuple is
    You dont know what a first class array is
    You dont know what a derive macro is
    You dont know what move by default means
    You dont know the Drop order of structs
    You dont know what UnsafeCell is
    You dont know what MaybeUninit is
    You dont know what checked arithmetic is
    You thought header files were necessary
    You didnt think Self could be a type

    • 1 month ago
      Anonymous

      >for i in (0 ..).map_while(|n| NonZeroUsize::new(100 >> n))
      Oh yes, this is MUCH easier than the c++ variant. Rust wins AGAIN

    • 1 month ago
      Anonymous

      >You dont know what a slice is
      >You dont know what a pattern is
      >You dont know what a proc macro is
      >You dont know what a first class tuple is
      >You dont know what a first class array is
      >You dont know what a derive macro is
      >You dont know what move by default means
      >You dont know the Drop order of structs
      >You dont know what UnsafeCell is
      >You dont know what MaybeUninit is
      >You dont know what checked arithmetic is
      >You thought header files were necessary
      >You didnt think Self could be a type
      Oh my reddit, what a fragile ego! Shut up you narcissistic baby. Nobody cares that you read the first 10 pages of Rust for Dummies.

  5. 1 month ago
    Anonymous

    Can't be worse than Zig's.

  6. 1 month ago
    Anonymous

    >established loop patterns
    They are C++ loop patterns. In Python for example, for loops are range based. C++ for loops are actually while loops. You gave an example too, dividing by 2 in each step probably fits better in a while loop because you aren't repeating something n times

    • 1 month ago
      Anonymous

      C++ doesn't have lazily evaluated iterators like Rust. Rust iter is more like Java streams.

      • 1 month ago
        Anonymous

        >C++ doesn't have lazily evaluated iterators
        I mean it kinda does, istream_iterator has to be lazy, doesn't it?
        Besides, it seems the "proper" way to do that in C++ now would be lazy range adaptors.

        • 1 month ago
          Anonymous

          >istream_iterator
          Oh nice. Can you make generator function into an integrator and compose them with zip, chain, etc like ok Rust?

          • 1 month ago
            Anonymous

            >integrator
            Iterator

            >ok
            In

            Frick autocorrection

          • 1 month ago
            Anonymous

            Yeah, but as I said before, rather than raw iterators, you should use range view adaptors.
            #include <ranges>
            #include <fmt/format.h>
            #include <fmt/ranges.h>

            int main() {
            using namespace std;

            auto squares_under_200 =
            views::iota(0)
            | views::transform([](int i){ return i*i;})
            | views::take_while([](int i){ return i < 200; });

            // {0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196}
            fmt::print("squares under 200: {}n", squares_under_200);
            }

            As usual with sepples, it's all very verbose. It's also only partially implemented in either GCC or clang, and it has some shitty kinks (i.e. anything non-shape preserving like "filter" will frick up vectorization). I think vectorization works in Rust because filter is shape preserving (i.e. it returns an optional instead of changing the range length), but they are timid about using Optionals everywhere in the C++ standard library.
            But hey I'll take what I can get.

          • 1 month ago
            Anonymous

            What have they done to C++?

          • 1 month ago
            Anonymous

            This is why you shouldn't take advice from rustoids.

    • 1 month ago
      Anonymous

      Also don't forget, loops are typically eagerly evaluated in cenile languages, while Rust In Rust, iterators are lazily evaluated. Rust's iterators are designed to follow a lazy evaluation model, which means that elements are produced one at a time and only when needed, which is major benefit for memory efficiency and allowing for more expressive and concise code

  7. 1 month ago
    Anonymous

    Iterators can have much better performance when dealing with non-contiguous containers and can be composed in a way that would be very long and ugly with regular for. Additionally, they make it easier for compiler to optimize your code, especially boundary checks.

  8. 1 month ago
    Anonymous

    Because they want to incorporate the Python and other scripted language users.
    You know why Rust is so memory safe and C/C++ is so very dangerous? C++ is going to be high end engineer level secret language like Fortran77 is now (some flight control systems to this day are still using it etc).
    So - it's a drive to reduce the amount of knowledgeable engineers. I.e. making the population more stupid.

    • 1 month ago
      Anonymous

      i'm not sure what you're saying anon but it sounds very schizo

    • 1 month ago
      Anonymous

      >So - it's a drive to reduce the amount of knowledgeable engineers. I.e. making the population more stupid.
      Computational Marxism rears its ugly head once more

    • 1 month ago
      Anonymous

      moronic Black person. You don't start a sentence with i.e.

    • 1 month ago
      Anonymous

      Why would you not engineer user friendly tools over the years? We have been doing this for centuries but now hipster kalemale luddites like you like to prove yourself by intentionally cucking yourself from engineering advancements like some sort of an autism cult.
      No one cares.

      • 1 month ago
        Anonymous

        Anon, are you being soft on programmers? The highest-paid work force in the entire global economy?

        • 1 month ago
          Anonymous

          Online Prostitution are highest paid jobs in the economy.

    • 1 month ago
      Anonymous

      not knowing le ebin c++ doesn't make the population any dumber

  9. 1 month ago
    Anonymous

    Bampu

  10. 1 month ago
    Anonymous
  11. 1 month ago
    Anonymous

    More like why did C ruin established loop patterns?

    Modula
    FOR Index := 1 TO 5 DO
    WriteInt(Index,5);
    END;
    Pascal
    for controlVariable := start to finalValue do
    begin
    statement;
    end;

    • 1 month ago
      Anonymous

      >Why did C ruin established loop patterns
      Because that pattern depends on integer control variables while C loops just state sections for each part of the loop. C's loop form is more adaptable because of it. Now explain why rust ruined the best notation for loops?

      • 1 month ago
        Anonymous

        C's for loop is just syntax sugar like a bunch of other things in the language that you mistakenly think of as "fundamental"

        • 1 month ago
          Anonymous

          >syntax sugar bad
          Then go program in assembly if you hate it so much.

        • 1 month ago
          Anonymous

          The loop as a concept is syntax sugar. It just covers up a goto and goto just covers up an assembly jump. The whole concept of a language itself is syntax sugar over assembly. b***hing about C loop because it syntax sugar is stupid.

          • 1 month ago
            Anonymous

            That's not what syntactic sugar is. The for loop in C is basically (I don't know if C acknowledges this) syntactic sugar for a while loop because
            for(statement1; condition; statement2)
            body
            [/cody]
            is exactly
            statement1;
            while(condition) {
            body;
            statement2;
            }

            and only that. Using gotos, there are multiple ways to implement a loop with the same semantics so you can't say this code is the other. Additionally viewing all programming languages as sugar over assembly sounds like lacking knowledge regarding programming languages. For example Prolog is more like syntactic sugar over first order logic and doesn't have constructs like loops and conditional jumps and it's variables don't work like registers to store values in but their values are deduced during the program (and that plays into running predicates "backwards", i.e. passing the desired result and getting back the inputs that would have given it). I'd say it has nothing to do with assembly

            >Its too terse
            This scares the soidevs
            for(int i=0; buf[i]! = ''; i++) {

            For this purpose in other languages you can write
            for c in buf:

            which is less characters (also you won't accidentally put a gap in != and waste time)

            >Too terse
            This is extremely ironic coming from the people who do this shit regularly.
            nums.into_iter().map(i32::unsigned_abs).collect()

            In other languages this is simply
            nums' = map abs nums

            Rust, being a low level systems language, wants to give more control to the programmer and so one has to be more explicit. The idea tho is you do this very often so why not place it in a special function instead of rewritting the same for loops that just apply a function to elements of your list everywhere (which is also error prone)

          • 1 month ago
            Anonymous

            >[/cody]
            You having a little bit of trouble there, chief?

        • 1 month ago
          Anonymous

          Why have loops in C at all? You could do all that with if/else and goto
          Shit, you don't even need else

      • 1 month ago
        Anonymous

        It's not the best notation for loops. People abuse all 3 sections of the for loop to do way too much for "terseness" and the comma operator is a very massive pitfall. I'm glad languages are disallowing for more explicit constructions.

        • 1 month ago
          Anonymous

          >Its too terse
          This scares the soidevs
          for(int i=0; buf[i]! = ''; i++) {

          • 1 month ago
            Anonymous

            You won't get any replies out of them. They are shitting their pants in fear.

          • 1 month ago
            Anonymous

            That's obviously not what I'm talking about. People doing multiple initializations, multiple conditions, and multiple (possibly non-obvious) increments all in a single for loop construct

          • 1 month ago
            Anonymous

            >small group of people misused something so it must be taken from everyone.
            Most people are not doing that shit in their code. You have taken the worse programmers and then projected them over the entire population of programmers.

            That's how buffer overflows happen. Null-terminated strings are another thing C changed from the established traditions.

            >null strings
            They are useful for the embedded space and honestly if you want a proper string its not that hard to write one yourself. C++ patched a perfectly fine implementation in.

            That's explicit, not terse

            >explicit
            Its the same kind of thing as the over stuffing of a for loop. You are doing like 20 things on one line because you want to chain everything together. The longer the chain goes on the more of the pain it is to read the code.

          • 1 month ago
            Anonymous

            >You have taken the worse programmers and then projected them over the entire population of programmers.
            No, the "best" C programmers are the one's that I've seen do that. The ones who do sane things with for loops are seen as pariahs

          • 1 month ago
            Anonymous

            That's how buffer overflows happen. Null-terminated strings are another thing C changed from the established traditions.

        • 1 month ago
          Anonymous

          >Too terse
          This is extremely ironic coming from the people who do this shit regularly.
          nums.into_iter().map(i32::unsigned_abs).collect()

          • 1 month ago
            Anonymous

            That's explicit, not terse

          • 1 month ago
            Anonymous

            You read every method as its own step. Turn nums into an iterator, map this function, collect it into a new container. If it's any longer than this then the autoformatter will put each step on its own line.
            Personally I don't mind C-style for loops too much, but it can be annoying how out of order they are, with the loop body technically coming before the third term and possibly touching the loop variable. Iterator chains are relatively more constrained (map applies to each element exactly once no matter what, etc) and ordered.

  12. 1 month ago
    Anonymous

    https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-for-range

  13. 1 month ago
    Anonymous

    cnile brainrot is real

  14. 1 month ago
    Anonymous

    >this makes the Cnile apoplectic
    int main(void)
    {
    Vec vec = c_init(Vec, {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 9, 10, 11, 12, 5});

    c_filter(Vec, vec
    , c_flt_skipwhile(*value < 3) // skip leading values < 3
    && (*value & 1) == 1 // then use odd values only
    && c_flt_map(*value * 2) // multiply by 2
    && c_flt_takewhile(*value < 20) // stop if mapped *value >= 20
    && printf(" %d", *value) // print value
    );
    // 6 10 14 2 6 18
    puts("");
    Vec_drop(&vec);
    }

  15. 1 month ago
    Anonymous

    Rust’s loop constructs differ from established patterns like those in C++ to enhance safety and expressiveness. Its for loop iterates directly over ranges and iterators, clearly conveying the sequence of values and avoiding common errors associated with traditional loop conditions. Rust’s while loop, used for conditions checked before each iteration, benefits from the language’s pattern matching, further reducing potential bugs and making code more intuitive. This design philosophy reflects Rust’s emphasis on safety, concurrency, and performance, aiming to streamline coding practices and prevent common programming errors.

    • 1 month ago
      Anonymous

      The internet is really dead.

  16. 1 month ago
    Anonymous

    every single language is so ugly when it comes to ranges when it could be simple
    for i in 1..99, 2

    // or the following which is python

    for i in range(1,99,2)

    • 1 month ago
      Anonymous

      Great idea, let's take it further
      assign(c, add(mul(a, b), sub(1, a*~~
      Maybe we can even get rid of those ugly commas somehow

Your email address will not be published. Required fields are marked *