Push Ifs Up and Fors Down
111–120 of 209 posts
Re: Push Ifs Up and Fors Down
#112Earlier quoted context omitted.
Functions should decide or act, not both.
But if that’s all you have, then how does your system do anything ? You ultimately need to be able to decide and then act based in that decision somewhere..
def doth_match(*args):
return True # the predicate
def doeth_thou(*args):
# processing things
return {} # status object for example
The framework loops and checks the first function; if true, then execute the second function. And then break or continue for other rule files (or objects).There could be multiple files rule1.py, rule2.py, etc that check and do different things.
Re: Push Ifs Up and Fors Down
#113This 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 internal functions which are called from at most two places, and only if the decision is out of their scope of concern.
Another idea is to make the function perform only the if statement, which calls two other helper functions.
If the caller needs to write a loop where the decision is to be hoisted out of the loop, the caller can use the lower-level "decoded-condition helpers". Callers which would only have a single if, not in or around a loop, can use the convenience function which hides the if. But we have to keep in mind that we are doing this for optimization. Optimization often conflicts with good program organization! Maybe it is not good design for the caller to know about the condition; we only opened it up so that we could hoist the condition outside of the caller's loop.
These dilemmas show up in OOP, where the "if" decision that is in the callee is the method dispatch: selecting which method is called.
Techniques to get method dispatch out of loops can also go against the grain of the design. There are some patterns for it.
E.g. wouldn't want to fill a canvas object with a raster image by looping over the image and calling canvas.putpixel(x, y, color). We'd have some method for blitting an image into a canvas (or a rectangular region thereof).
Re: Push Ifs Up and Fors Down
#114My 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.
Re: Push Ifs Up and Fors Down
#115Push everything down for better code readability printInvoice(invoice, options) // is much better than if(printerReady){ if(printerHasInk){ if(printerHasPaper){ if(invoiceFormatIsPortrait){ : The same can be said of loops printInvoices(invoices) // much better than for(invoice of invoices){ printInvoice(invoice) } At the end, while code readability is extremely important, encapsulation is much more important, so mix…
> demonstrates arrow anti-pattern
Ewwww gross. No. Do this instead:
if(!printerReady){ return; } if(!printerHasInk){ return; } if(!printerHasPaper){ return; } if(!invoiceFormatIsPortrait){ return; }
Way more readable than an expanding arrow.
> printInvoices(invoices) // much better than
But yes, put the loop into its own function with all of the other assumptions already taken care of? This is good.
Re: Push Ifs Up and Fors Down
#116In some cases you want to do the opposite - to utilize SIMD. With AVX-512 for example, trivial branching can be replaced with branchless code using the vector mask registers k0-k7, so an if inside a for is better than the for inside the if, which may have to iterate over a sequence of values twice. To give a basic example, consider a loop like: for (int i = 0; i We can convert this to one which operates on 16 ints pe…
Re: Push Ifs Up and Fors Down
#117In some cases you want to do the opposite - to utilize SIMD. With AVX-512 for example, trivial branching can be replaced with branchless code using the vector mask registers k0-k7, so an if inside a for is better than the for inside the if, which may have to iterate over a sequence of values twice. To give a basic example, consider a loop like: for (int i = 0; i We can convert this to one which operates on 16 ints pe…
My first thought was conditional branches inside the for loop based on the element as well. By any chance, do you know how hard it is for compilers to auto-vectorize something like this? I am generally not sure where the boundary is.
Re: Push Ifs Up and Fors Down
#118My 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…
I used to try and form these kinds of rules and heuristics for code constructs, but eventually accepted they're at the wrong level of abstraction to be worth keeping around once you write enough code.
It's telling they tend to resort to made up function names or single letters because at that point you're setting up a bit of a punching bag with an "island of code" where nothing exists outside of it, and almost any rule can make sense.
-
Perfect example is the "redundancies and dead conditions" mentioned: we're making the really convenient assumption that `g` is the only caller of `h` and will forever be the only caller of `h` in order to claim we exposed a dead branch using this rule...
That works on the island, but in an actual codebase there's typically a reason why `g` and `h` weren't collapsed into each other to start.
Re: Push Ifs Up and Fors Down
#119> 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…