• baseless_discourse@mander.xyz
    link
    fedilink
    arrow-up
    5
    ·
    edit-2
    4 months ago

    Honestly, it is much more code to use loop with non-local control like break, continue etc. (variable initialization, append, variable mutation in loops…) than just calling a collect function (which I assume just means to_list). In the above example, in most programming language I know, you don’t even need to collect the result into a list.

    Not to mention, large loops with non-local control is a breeding ground for spegatti code. Because you no longer have a consistent exit point to the loop, thus making the semantics hard o reason about.

    In many languages, there are type class / trait / interfaces (whatever you want to call them) that allows lazy structures to share the same API as strict ones.

    • mbtrhcs
      link
      fedilink
      arrow-up
      3
      ·
      4 months ago

      Yeah, in Java calling first() on a stream is the same as an early return in a for-loop, where for each element all of the previous stream operations are applied first.

      So the stream operation

      cars.stream()
          .filter(c -> c.year() < 1977)
          .first()
      

      is equivalent to doing the following imperatively

      for (var car : cars) {
          if (car.year() < 1977) return car;
      }
      

      Not to mention Kotlin actually supports non-local returns in lambdas under specific circumstances, which allows for even more circumstances to be expressed with functional chaining.

      • nous@programming.dev
        link
        fedilink
        English
        arrow-up
        4
        ·
        4 months ago

        These are not quite equivalent. In terms of short-circuiting yeah they both short-circuit when they get the value. But the latter is returning from the current function and the former is not. If you add a return to that first example then they are equivalent. But then cannot be used in line. Which is a nice advantage to the former - it can be used inline with less faff as you can just assign the return to a value. The latter needs you to declare a variable, assign it and break from the loop in the if.

        Personally I quite like how the former requires less modification to work in different contexts and find it nicer to read. Though not all logic is easier to read with a stream, sometimes a good old for loop makes the code more readable. Use which ever helps you best at each point. Never blindly apply some pattern to every situation.