Live data from Hacker News

Push Ifs Up and Fors Down

matklad.github.io

21–30 of 209 posts

Re: Push Ifs Up and Fors Down

#21
A more general rule is to push ifs close to the source of input: https://gieseanw.wordpress.com/2024/06/24/dont-push-ifs-up-p...

It's really about finding the entry points into your program from the outside (including data you fetch from another service), and then massaging in such a way that you make as many guarantees as possible (preferably encoded into your types) by the time it reaches any core logic, especially the resource heavy parts.

Re: Push Ifs Up and Fors Down

#22

Terrible advice. It's the exact opposite of "Tell, don't ask". Performance of an if-statement and for-loop are negligent. That's not the bottleneck of your app. If you're building something that needs to be highly performant, sure. But that's not the majority. https://martinfowler.com/bliki/TellDontAsk.html

consider his another post in somewhat similar spirit: https://tigerbeetle.com/blog/2024-12-19-enum-of-arrays/ the author is indeed working in a performance-oriented niche

Re: Push Ifs Up and Fors Down

#23

Code complexity scanners⁰ eventually force pushing ifs down. The article recommends the opposite: By pushing ifs up, you often end up centralizing control flow in a single function, which has a complex branching logic, but all the actual work is delegated to straight line subroutines. ⁰ https://docs.sonarsource.com/sonarqube-server/latest/user-gu...

[deleted]

Re: Push Ifs Up and Fors Down

#24

Terrible advice. It's the exact opposite of "Tell, don't ask". Performance of an if-statement and for-loop are negligent. That's not the bottleneck of your app. If you're building something that needs to be highly performant, sure. But that's not the majority. https://martinfowler.com/bliki/TellDontAsk.html

Performance of any given CPU instruction is negligible, yet somehow they accumulate to noticeable values.

Re: Push Ifs Up and Fors Down

#26

Code complexity scanners⁰ eventually force pushing ifs down. The article recommends the opposite: By pushing ifs up, you often end up centralizing control flow in a single function, which has a complex branching logic, but all the actual work is delegated to straight line subroutines. ⁰ https://docs.sonarsource.com/sonarqube-server/latest/user-gu...

There was a thread yesterday about LLMs where somebody asked "what other unreliable tool people accept for coding?"

Well, now I have an answer...

Re: Push Ifs Up and Fors Down

#27

Code complexity scanners⁰ eventually force pushing ifs down. The article recommends the opposite: By pushing ifs up, you often end up centralizing control flow in a single function, which has a complex branching logic, but all the actual work is delegated to straight line subroutines. ⁰ https://docs.sonarsource.com/sonarqube-server/latest/user-gu...

I've always hated code complexity scanners ever since I noticed them complaining about perfectly readable large functions. It's a lot more readable when you have the logic in one place, and you should only be trying to break it up when the details cause you to lose track of the big picture.

Re: Push Ifs Up and Fors Down

#28

This article doesn't explain the benefits of the suggested approach well enough. And the last example looks like a poor advice and contradicts previous advice: there's rarely a global condition that is enough to check once at the top: the condition usually is inside the walrus. And why do for walrus in pack {walrus.throbnicate()} instead of making throbnicate a function accepting the whole pack?

[deleted]

Re: Push Ifs Up and Fors Down

#29
post #20
post #2

I agree, except for this example, where the author effectively (after a substitution) prefers the former: fn f() -> E { if condition { E::Foo(x) } else { E::Bar(y) } } fn g(e: E) { match e { E::Foo(x) => foo(x), E::Bar(y) => bar(y) } } The latter is not only more readable, but it is safer, because a match statement can ensure all possibilities are covered.

> The latter is not only more readable, but it is safer, because a match statement can ensure all possibilities are covered. Whether or not this matters depends on what, exactly, is in those match arms. Sometimes there's some symmetry to the arms of an if statement. And in that case, being exhaustive is important. But there's plenty of times where I really just have a bit of bookkeeping to do, or an early return or s…

It's only exhaustive in this toy case. Add another one and the burden of checking for exhaustiveness with ifs falls on your shoulders.

Re: Push Ifs Up and Fors Down

#30
I agree that the first example in the article is "bad"...

  fn frobnicate(walrus: Option)`)
but the rest makes no sense to me!

  // GOOD
  frobnicate_batch(walruses)
  // BAD
  for walrus in walruses {
    frobnicate(walrus)
  }
It doesn't follow through with the "GOOD" example though...

  fn frobnicate_batch(walruses)
    for walrus in walruses { frobnicate(walrus) }
  }
What did that achieve?

And the next example...

  // GOOD
  if condition {
    for walrus in walruses { walrus.frobnicate() }
  } else {
    for walrus in walruses { walrus.transmogrify() }
  }
  // BAD
  for walrus in walruses {
    if condition { walrus.frobnicate() }
    else { walrus.transmogrify() }
  }
What good is that when...

  walruses = get_5_closest_walruses()
  // "GOOD"
    if walruses.has_hungry() { feed_them_all() }
    else { dont_feed_any() }
  // "BAD"
    for walrus in walruses {
       if walrus.is_hungry() { feed() }
       else { dont_feed() }
Post reply on HN