Live data from Hacker News

Push Ifs Up and Fors Down

matklad.github.io

141–150 of 209 posts

Re: Push Ifs Up and Fors Down

#141
post #105

My weird mental model: You have a tree of possible states/program flow. Conditions prune the tree. Prune the tree as early as possible so that you have to do work on fewer branches. Don’t meticulously evaluate and potentially prune every single branch, only to find you have to prune the whole limb anyways. Or even weirder: conditionals are about figuring out what work doesn’t need to be done. Loops are the “work.” Ul…

Can I float an adjacent model? Classes are nouns, functions are verbs.

[deleted]

Re: Push Ifs Up and Fors Down

#142
post #29

Earlier quoted context omitted.

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

So long as you have an else block on your if statement, it’s exhaustive. I think I can keep track of that.

Just because your code flowed into the else block, it does not mean the condition got handled properly. If different switching values don't need special treatment, why have an if statement at all? Consider serving an ML model, and switching on the provider. Let's say you initially support OpenAI, and self-hosting, as the if and else cases, respectively. If you then add support for Anthropic, it will incorrectly follow the else path and be treated as self-hosted. Or you make else the error path, and fail when you should not have.

Re: Push Ifs Up and Fors Down

#143

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…

Doesn't this obfuscate what assumptions you can make when trying to understand the core logic? You prefer to examine all the call chains everywhere?

No I don't think so because if you make your assumptions early then the same assumptions exist in the entire program and that makes them easy to reason about

Re: Push Ifs Up and Fors Down

#144
post #135
post #93

Earlier quoted context omitted.

To add to this, a pattern that's really helpful here is: findThingWeShouldDoThisTo can both satisfy a condition and greatly simplify doThis if you can pass it the thing in question. It's read-only, testable, and readable. Highly recommend.

This is not obvious to me. The whole point was to separate the conditionals from the actions. In your example, it’s not clear if/how much “should we do this” logic is in your function. If none, then great; you’ve implemented a find or lookup function and I agree those can be helpful. If there’s some logic, eg you have to iterate through a set or query a database to find all the things that meet the criteria for “shou…

let list = findHumansToKill();

//list = [];

killHumans(list);

Re: Push Ifs Up and Fors Down

#145
For optimization, sure, but there are also cases where you care more about a maintainable expression of business rules, or the mental model used by subject experts.

Re: Push Ifs Up and Fors Down

#146

> If there’s an if condition inside a function, consider if it could be moved to the caller instead This idle conjecture is too rife with counterexamples. - If the function is called from 37 places, should they all repeat the if statement? - What if the function is getaddrinfo , or EnterCriticalSection ; do we push an if out to the users of the API? I think that we can only think about this transformation for interna…

If the function is called from 37 places, you need to refactor your code, but to answer your question on that point: it depends. DRY feels like the right answer, but I think we'd have to review an actual code example to decide. On examples where you're talking about a library function, I think you have to accept that as a library you're in a special place: you're on an ownership boundary. Data is moving across domain…

Pray tell, how many places is appropriate to call the same function? Is 5 too many? How about 6? When I hit 7, I have to refactor everything, right?

Re: Push Ifs Up and Fors Down

#147

> If there’s an if condition inside a function, consider if it could be moved to the caller instead This idle conjecture is too rife with counterexamples. - If the function is called from 37 places, should they all repeat the if statement? - What if the function is getaddrinfo , or EnterCriticalSection ; do we push an if out to the users of the API? I think that we can only think about this transformation for interna…

If the function is called from 37 places, you need to refactor your code, but to answer your question on that point: it depends. DRY feels like the right answer, but I think we'd have to review an actual code example to decide. On examples where you're talking about a library function, I think you have to accept that as a library you're in a special place: you're on an ownership boundary. Data is moving across domain…

Refactoring due to being called more than N times seems very function dependent. As the prior author noted, I’d expect to call a lock function in some programs a lot. Likewise, memcpy. In fact I’d argue that well factored functionality is often called at many different call sites.

Re: Push Ifs Up and Fors Down

#148
These are extremely opinionated, and shouldn't be treated as a rule of thumb. As somebody else said, there isn't a rule of thumb here at all, but if I was to make up one, I would probably tell you the opposite:

- You have to push ifs down, because of DRY.

- If performance allows, you should consider pushing fors up, because then you have the power of using filter/map/reduce and function compositions to choose what actions you want to apply to which objects, essentially vectorizing the code.

Re: Push Ifs Up and Fors Down

#150
post #135

Earlier quoted context omitted.

This is not obvious to me. The whole point was to separate the conditionals from the actions. In your example, it’s not clear if/how much “should we do this” logic is in your function. If none, then great; you’ve implemented a find or lookup function and I agree those can be helpful. If there’s some logic, eg you have to iterate through a set or query a database to find all the things that meet the criteria for “shou…

let list = findHumansToKill(); //list = []; killHumans(list);

[deleted]
Post reply on HN