Recipes, not loops!
If you're accustomed to writing loops to transform data, stop! Deephaven works fundamentally differently, and understanding this difference early saves you frustration and helps you write better, faster code.
The fundamental paradigm shift: recipes, not loops
How you might think
In traditional programming, you tell the computer exactly how to process each element:
This loop processes one element at a time. You're giving step-by-step instructions for how to process the data.
How to think in Deephaven
In Deephaven, you specify what you want, not how to compute it. You write a recipe that describes the transformation, and the engine figures out the optimal way to execute it. Table operations such as update take recipes as query strings:
There's no loop. You describe the relationship (XSquared = X * X), and the engine applies it to every row. This works the same way for arbitrarily complex operations.
When you write XSquared = X * X, you're not saying:
- "Start at row 0"
- "Read
Xfrom row 0" - "Multiply
Xby itself" - "Store the result in
XSquaredat row 0" - "Go to row 1"
- "Repeat..."
You're saying:
- "For every row,
XSquaredshould equalXtimesX"
The engine decides:
- How to split the data into batches of rows for fast processing.
- Whether to parallelize the operation.
- Which rows to recompute when data changes.
Why this matters
For static data
Even for static, one-time calculations, the recipe approach has advantages:
- Clearer code — declarative recipes are easier to read than imperative loops.
- Faster execution — the engine evaluates formulas over batches of rows in compiled code.
- Less error-prone — no manual loop management or index tracking.
For real-time data
This is the critical difference. Loops execute once and stop. Recipes keep applying to new rows as they arrive.
Watch what happens:
- The table keeps updating — new rows appear about every second.
- You wrote the recipe once, and the engine applies it to every new row.
Compare a loop that uses a column iterator to read values one at a time:
The engine is smart about updates
When the source data changes, the engine:
- Tracks dependencies — it knows that
XSquareddepends onX. - Computes incrementally — each update tells the engine which rows were added, which existing rows changed (modified rows), and which columns changed. The engine computes
XSquaredfor the added rows. For modified rows, it recomputesXSquaredonly whenXis one of the changed columns. - Updates results in place — it writes the new values into the result table, so you never re-run the query.
With loops, this requires significant additional infrastructure. A loop executes once and stops, so you'd have to write your own code to detect new and changed rows and recompute them. With recipes, it's automatic.
Common patterns: wrong vs. right
You've already seen the simplest pattern, creating a column from another column, in How to think in Deephaven. Two other common loops have recipe equivalents.
Pattern: conditional logic
❌ Wrong (loop approach):
✅ Right (recipe with the ternary-if operator). The operator has the form condition ? valueIfTrue : valueIfFalse:
Pattern: running calculations
❌ Wrong (loop with accumulator):
✅ Right (use updateBy):
When loops are appropriate
Recipes replace loops for transforming data, but loops are still the right tool for extracting data from a table and for control flow in your own code.
✅ Extracting data from Deephaven
To read two columns side by side, open one iterator per column and advance them together, closing both when you're done:
See the guide to extracting table values for details.
✅ Control flow in your Groovy code
A loop over ordinary Groovy values is fine when each iteration builds a query rather than reading table rows. Here, the loop creates one filtered table per symbol, and each table is still a live recipe.
Next steps
- Continue to the next chapter, Real-time plots, to visualize static and ticking tables.
- Read Think like a ninja for more examples.
- Read Vectorization and the recipe paradigm for technical details.
- See rolling aggregations with
updateByfor more recipes.