Push Ifs Up and Fors Down
71–80 of 209 posts
Re: Push Ifs Up and Fors Down
#72Re: Push Ifs Up and Fors Down
#73Add asserts to the end of the function too.
Loop's can live in the middle, take as much I/O and compute out of the loop as you can :)
Re: Push Ifs Up and Fors Down
#74With conditionals, it's also useful to express them as ternary assignment when possible. This makes it more likely the optimizer will generate a conditional move instead of a branch. When the condition is not sufficiently predictable, a conditional move is far faster due to branch misprediction. Sometimes it's not always faster in the moment, but it can still alleviate pressure on the branch prediction cache.
Re: Push Ifs Up and Fors Down
#75It’s a bit niche for HN, but SwiftUI rendering works way better when following this. In a ForEach, you really shouldn’t have any branching, or you‘ll pay quite catastrophic performance penalties. I found out the hard way when rendering a massive chart with Swift Charts. All branching must be pushed upwards.
Why? Does it interpret the code?
Re: Push Ifs Up and Fors Down
#76Sometimes I like to put the conditional logic in the callee because it prevents the caller from doing things in the wrong order by accident. Like for example, if you want to make an idempotent operation, you might first check if the thing has been done already and if not, then do it. If you push that conditional out to the caller, now every caller of your function has to individually make sure they call it in the rig…
Maybe write the functions without the checks, then have wrapper functions that just do the checks and then call the internal function?
Re: Push Ifs Up and Fors Down
#77Sometimes I like to put the conditional logic in the callee because it prevents the caller from doing things in the wrong order by accident. Like for example, if you want to make an idempotent operation, you might first check if the thing has been done already and if not, then do it. If you push that conditional out to the caller, now every caller of your function has to individually make sure they call it in the rig…
You’ve kind of answered your own question here. > If you push that conditional out to the caller, now every caller of your function has to individually make sure they call it in the right way to get a guarantee of idempotency In this situation your function is no longer idempotent, so you obviously can’t provide the guarantee. But quite frankly, if you’re having to resort to making individual functions implement stat…
Re: Push Ifs Up and Fors Down
#78My 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…
Re: Push Ifs Up and Fors Down
#79This part in particular seems like an aesthetic judgment, and I disagree. I find it more natural to follow a flowchart than to stare at one.
> A related pattern here is what I call “dissolving enum” refactor.... There are two branching instructions here and, by pulling them up, it becomes apparent that it is the exact same condition, triplicated (the third time reified as a data structure):
The problem here isn't the code organization, but the premature abstraction. When you write the enum it should be because "reifying the condition as a data structure" is an intentional, purposeful act. Something that empowers you to, for example, evaluate the condition now and defer the response to the next event tick in a GUI.
> The primary benefit here is performance. Plenty of performance, in extreme cases.
Only if so many other things go right. Last I checked, simply wanting walruses to behave polymorphically already ruins your day, even if you've chosen a sufficiently low-level programming language.
A lot of the time, the "bad" code is the implementation of the function called in the "good" code. That makes said function easier to understand, by properly separating responsibilities (defining frobnication and iterating over walruses). Abstracting the inner loop to a function also makes it sane to express the iteration as a list comprehension without people complaining about how you have these nested list comprehensions spread over multiple lines, and why can't you just code imperatively like the normal programmers, etc.
> The two pieces of advice about fors and ifs even compose!
1. The abstraction needed to make the example comprehensible already ruins the illusion of `frobnicate_batch`.
2. If you're working in an environment where this can get you a meaningful performance benefit and `condition` is indeed a loop invariant (such that the transformation is correct), you are surely working in an environment where the compiler can just hoist that loop invariant.
3. The "good" version becomes longer and noisier because we must repeat the loop syntax.
> jQuery was quite successful back in the day, and it operates on collections of elements.
That's because of how it allowed you to create those collections (and provided iterators for them). It abstracted away the complex logic of iterating over the entire DOM tree to select nodes, so that you could focus on iterating linearly over the selected nodes. And that design implicitly, conceptually separated those steps. Even if it didn't actually build a separate container of the selected nodes, you could reason about what you were doing as if it did.
Re: Push Ifs Up and Fors Down
#80Earlier quoted context omitted.
You can't shove every single assumption into the type system...
You can and should put as many as you can there https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... If instead of validating that someone has sent you a phone number in one spot and then passing along a string, you can as easily have a function construct an UncheckedPhoneNumber. You can choose to only construct VerifiedPhoneNumbers if the user has gone through a code check. Both would allow you to pluck a…