> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gorules.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing expressions

> Transform and calculate data using the ZEN expression language.

export const ExpressionViz = ({entries = []}) => {
  const allCells = entries.flatMap((entry, i) => [<div key={`key-${i}`} style={{
    backgroundColor: '#dbeafe',
    color: '#1e40af',
    padding: '12px 16px',
    borderRadius: '8px',
    fontFamily: 'ui-monospace, monospace',
    fontSize: '14px',
    fontWeight: '500'
  }}>
      {entry.key}
    </div>, <div key={`val-${i}`} style={{
    backgroundColor: '#ffffff',
    color: '#334155',
    padding: '12px 16px',
    borderRadius: '8px',
    fontFamily: 'ui-monospace, monospace',
    fontSize: '14px',
    border: '1px solid #e2e8f0'
  }}>
      {entry.value}
    </div>]);
  return <div style={{
    backgroundColor: '#f1f5f9',
    borderRadius: '12px',
    padding: '20px',
    margin: '16px 0'
  }}>
      <div style={{
    display: 'grid',
    gridTemplateColumns: 'auto 1fr',
    gap: '8px'
  }}>
        {allCells}
      </div>
    </div>;
};

Expression nodes transform data using the ZEN expression language. Use them to calculate values, reshape data, and prepare outputs.

<video autoPlay loop muted playsInline style={{ width: '100%', borderRadius: '8px' }}>
  <source src="https://mintcdn.com/gorules/_eSfZVSvlKqfwnSP/videos/Expression.mp4?fit=max&auto=format&n=_eSfZVSvlKqfwnSP&q=85&s=202d31383f4a8a578dd793114e37e027" type="video/mp4" data-path="videos/Expression.mp4" />
</video>

## Creating an expression node

1. Drag an **Expression** node onto the canvas
2. Connect it to your data flow
3. Click **Edit Expression** to open the editor
4. Define output fields and their expressions

## Expression structure

Each expression node produces an output object. You define fields and the expressions that calculate them:

<ExpressionViz
  entries={[
{ key: "subtotal", value: "sum(map(items, #.price * #.quantity))" },
{ key: "tax", value: "subtotal * taxRate" },
{ key: "shipping", value: "subtotal > 100 ? 0 : 9.99" },
{ key: "total", value: "subtotal + tax + shipping" }
]}
/>

## Accessing data

Reference input data using dot notation:

```
customer.name           // Nested object access
order.items[0].price    // Array indexing
```

### Referencing previous nodes

Use `$nodes` to access output from any upstream node by its name:

```
$nodes.CreditCheck.rating       // Output from "CreditCheck" node
$nodes.RiskScore.value          // Output from "RiskScore" node
$nodes["My Node"].field         // Use brackets for names with spaces
```

See [Useful patterns](/learn/authoring/patterns#referencing-previous-nodes-with-nodes) for more examples.

## Operators

### Arithmetic

```
price * quantity        // Multiplication
total / count           // Division
base + bonus            // Addition
gross - deductions      // Subtraction
amount % 100            // Modulo (remainder)
2 ^ 10                  // Power (1024)
```

### Comparison

```
age >= 18               // Greater than or equal
status == "active"      // Equal
tier != "basic"         // Not equal
score < threshold       // Less than
```

### Logical

```
isActive and hasPermission    // Both must be true
isAdmin or isOwner            // Either can be true
not isBlocked                 // Negation
```

### Ternary (conditional)

```
score > 70 ? "pass" : "fail"
age >= 18 ? "adult" : age >= 13 ? "teen" : "child"
```

### Null handling

```
user.nickname ?? user.name ?? "Anonymous"    // First non-null value
```

### Range checks

```
age in [18..65]         // Inclusive range
score in (0..100)       // Exclusive range
value not in [1..10]    // Outside range
```

## Built-in functions

### Math

| Function   | Example             | Result |
| ---------- | ------------------- | ------ |
| `abs(n)`   | `abs(-5)`           | `5`    |
| `round(n)` | `round(3.7)`        | `4`    |
| `floor(n)` | `floor(3.9)`        | `3`    |
| `ceil(n)`  | `ceil(3.1)`         | `4`    |
| `min(arr)` | `min([3, 1, 4])`    | `1`    |
| `max(arr)` | `max([3, 1, 4])`    | `4`    |
| `sum(arr)` | `sum([1, 2, 3])`    | `6`    |
| `avg(arr)` | `avg([10, 20, 30])` | `20`   |

### String

| Function                | Example                     | Result          |
| ----------------------- | --------------------------- | --------------- |
| `len(s)`                | `len("hello")`              | `5`             |
| `upper(s)`              | `upper("hello")`            | `"HELLO"`       |
| `lower(s)`              | `lower("HELLO")`            | `"hello"`       |
| `trim(s)`               | `trim("  hi  ")`            | `"hi"`          |
| `contains(s, sub)`      | `contains("hello", "ell")`  | `true`          |
| `startsWith(s, prefix)` | `startsWith("hello", "he")` | `true`          |
| `split(s, delim)`       | `split("a,b,c", ",")`       | `["a","b","c"]` |

### Array

| Function             | Example                       | Result      |
| -------------------- | ----------------------------- | ----------- |
| `len(arr)`           | `len([1, 2, 3])`              | `3`         |
| `map(arr, expr)`     | `map([1, 2, 3], # * 2)`       | `[2, 4, 6]` |
| `filter(arr, expr)`  | `filter([1, 2, 3, 4], # > 2)` | `[3, 4]`    |
| `some(arr, expr)`    | `some([1, 2, 3], # > 2)`      | `true`      |
| `all(arr, expr)`     | `all([1, 2, 3], # > 0)`       | `true`      |
| `flatMap(arr, expr)` | `flatMap([[1,2], [3]], #)`    | `[1,2,3]`   |

The `#` symbol represents each element when iterating over arrays.

### Date

| Function             | Example                                     | Result       |
| -------------------- | ------------------------------------------- | ------------ |
| `d(str)`             | `d("2024-01-15")`                           | Date object  |
| `d().year()`         | `d("2024-01-15").year()`                    | `2024`       |
| `d().month()`        | `d("2024-01-15").month()`                   | `1`          |
| `d().day()`          | `d("2024-01-15").day()`                     | `15`         |
| `d().add(n, unit)`   | `d("2024-01-15").add(7, "d")`               | 7 days later |
| `d().diff(d2, unit)` | `d("2024-01-15").diff("2024-01-01", "day")` | `14`         |

## Common patterns

### Calculate totals

<ExpressionViz
  entries={[
{ key: "itemTotal", value: "sum(map(items, #.price * #.qty))" },
{ key: "discount", value: "itemTotal * discountRate" },
{ key: "finalTotal", value: "itemTotal - discount" }
]}
/>

### Categorize values

<ExpressionViz
  entries={[
{ key: "tier", value: "score >= 90 ? 'gold' : score >= 70 ? 'silver' : 'bronze'" },
{ key: "qualified", value: "tier in ['gold', 'silver']" }
]}
/>

### Work with dates

<ExpressionViz
  entries={[
{ key: "age", value: "d().diff(birthDate, 'year')" },
{ key: "isAdult", value: "age >= 18" },
{ key: "expiresAt", value: "d().add(30, 'd')" }
]}
/>
