Pimp My IDE / garage dispatchBack to the garage
October 7, 2026 / code shape / hot loops

Move the decision. Keep the proof.

"Push ifs up and fors down" can turn scattered branches into one visible decision and one clean batch. It is a refactoring test, not a spell.

A faster loop is wrong if the rewrite changes which work runs.

The shape is simple.

TigerBeetle's coding guide says to keep switch and if statements in a parent function when splitting code. Helpers should handle straight-line work. The guide names the rule "push ifs up and fors down."[1]

Matklad's original note gives both halves. A caller can reject an absent value before calling a function that accepts only a present value. A batch function can own the loop instead of making every caller repeat it. When one condition applies to a whole batch, placing the branch outside the loop avoids testing it for every item.[2]

Put the decision where it can be reviewed once. Put repeated work where it can be optimized as a batch.

The type can carry the check.

A function that accepts Option<Walrus> must decide what absence means. A function that accepts Walrus does not. Moving the absence check to the caller narrows the callee's valid input. The signature records that narrower contract.

This can make dead branches easier to see because the parent holds the control flow. It can also remove repeated checks. Neither result is automatic. If several callers need different absence policies, forcing one policy upward may make the parent harder to read.

Legality comes before speed.

Debasish Ghosh connects the idiom to query planning and filter-map laws. Database optimizers evaluate eligible selections near their inputs so later joins handle less data. The direction names differ because a query plan is drawn as a tree, but the practical move is the same: reduce the input before expensive combination.[3]

The article also states the limits. A condition can leave a loop only when it is invariant for that loop. A selection can cross a join only when it depends on columns available on the chosen side. Moving a filter ahead of a map preserves results only with the corresponding predicate transformation. It saves work only when that transformed predicate is cheaper than running the map.

Python's language reference makes clause order concrete. A comprehension nests its for and if clauses from left to right. Later clauses may depend on values produced by earlier ones. Reordering those clauses can change meaning, scope, or evaluation behavior.[4]

Review the effects too.

Equality on paper is not enough when a predicate, mapping function, iterator, or branch has side effects. Check exceptions, logging, mutation, ordering, and early exits. A rewrite that calls the same functions in a new order can produce a different program.

Keep one before-and-after fixture. Count calls to expensive work. Test empty input, one survivor, no survivors, and a boundary value. Benchmark only after the result and effects match.

Use this rewrite card.

BRANCH + BATCH REVIEW
SCENARIO=[BRANCH IN LOOP / FILTER MAP / QUERY FILTER]
INVARIANT_OR_DEPENDENCY=[EXACT CONDITION]
ORIGINAL_ORDER=[CALL SEQUENCE]
PROPOSED_ORDER=[CALL SEQUENCE]
RESULT_FIXTURE=[INPUT + EXPECTED OUTPUT]
EFFECT_FIXTURE=[CALLS + ERRORS + MUTATION]
MEASUREMENT=[BASELINE + CANDIDATE]
STATUS=[REWRITE CANDIDATE / NOT PROVEN]
Interactive makeover / branch and batch transfer case

Draft the proof before shifting the code.

Traditional purpose replaced: a refactoring checklist beside a diff. Better version: one scenario selector changes both code panes, three native checks drive a connected proof shaft, and the rig prints a copyable review card. A completed rig means the questions are selected. It does not prove the rewrite.

Select shapeCheck legalityCompare effectsMeasure work

Shift selector

Choose the code shape. Then select each review section you will require.

Rewrite scenario
Required proof sections

Transfer readout

The shaft fills as review sections are selected. Amber means draft work remains. Green is reserved for a filled template, not a proven rewrite.

Decision to batch shaft0 of 3 selected
Original shapebranch per item
Candidate shapebranch once
Review stateTemplate incomplete
Before
for item in items:
    if mode == "fast":
        fast(item)
    else:
        safe(item)
Candidate
if mode == "fast":
    fast_batch(items)
else:
    safe_batch(items)
Sources read / October 7, 2026

Source log

Open the evidence boundary
  1. Tiger Style, read October 7, 2026. The coding guide recommends centralizing parent control flow, moving non-branchy work to helpers, keeping leaf functions pure, and batching external events.
  2. Push Ifs Up And Fors Down by matklad, published November 15, 2023. It gives the caller-precondition, dissolved-enum, batch-operation, and branch-outside-loop examples.
  3. Push Ifs Up and Fors Down: The Idiom, Its Algebra, and Its Limits by Debasish Ghosh, read October 7, 2026. It covers query-plan vocabulary, filter-map equivalence, savings conditions, and legal-move limits.
  4. Python language reference: displays for lists, sets and dictionaries, version 3.14.8 documentation read October 7, 2026. It specifies left-to-right nesting and the dependency rules for comprehension clauses.
  5. Hacker News item 49997073, resolved through the official API and read October 7, 2026. It was the discovery route. Technical claims above come from the linked articles and language documentation.

Evidence boundary: the examples were reviewed as code-shape teaching material. No compiler optimization claim was benchmarked. No database plan was executed. The transfer case drafts a review card and switches illustrative snippets. It does not parse code, prove equivalence, or measure performance.