CH07-L04 · applied

Intermediate state and safe selection

Carry a computed result through a one-item list and guard access to index 0.

General CELRuns hereDocumented
What will I learn?

You can use a map as intermediate state, check the result count, and only then read the first item safely.

Where will I try it?

Directly below, in the browser playground.

What do I do?

Run both modes, compare where their values come from, then complete the task.

Try CEL · browser pilot

Try both ways to supply values

Define local values inside one CEL expression, or provide variables as JSON input. Everything runs in your browser.

CEL pilot subset
One self-contained CEL expressioncel.bind() gives a local name to a value and returns the result of the final expression.

cel.bind()cel.bind() is an optional official extension. It is not part of the core CEL language and may not be enabled by every host application.

Tip: press Ctrl/⌘ + Enter to run.
Result

Press Run CEL to evaluate the active example.

Pilot scope: literals, explicit conversions, local cel.bind() variables, JSON variables, lists, maps, presence, collection macros, core string checks, time values, arithmetic, comparisons, logic, and the conditional operator.

What you will do

Calculate a list of matches once, store it in a helper map, and check its size before using index 0. You will also see the general one-item-list pattern for carrying an intermediate result.

How it works

[{'matches': candidates.filter(candidate, candidate.active)}]
  .map(state,
    state.matches.size() > 0
      ? state.matches[0].name
      : 'not-found')
  [0]

The outer list contains exactly one helper map. map() therefore runs its body once and gives the name state to the calculated matches. Because map() returns another one-item list, the final index selects the result value.

Evaluation step by step

  1. filter() finds the active candidate Maya.
  2. The helper map is {'matches': [{'name': 'Maya', 'active': true}]}.
  3. size() > 0 is true, so access to matches[0] is safe.
  4. The inner result is 'Maya', and the outer [0] selects it from the list.

When there is no active candidate, the condition returns 'not-found' without reading a missing item.

Your task

  1. Run the prepared expression.
  2. Set active: false for both candidates.
  3. Remove the size() > 0 guard and try to read state.matches[0].name directly.

Expected observation: With no match, the guarded version returns 'not-found'; direct access to index 0 fails.

Common mistake

The outer [0] is safe only because you construct its list with one item. The state.matches.size() condition guards a different list — the filter result, which can be empty.

Show the explanation

The expression contains two different lists. The one-item wrapper always has size 1, while matches can have any size from 0 through the number of candidates.

Knowledge check

Which of the two lists needs a size check, and why?

Key takeaway

A helper map can carry intermediate state, but every indexed access needs a guarantee that the required list item exists.

Sources

  • CEL-DEV — official overview of CEL and its collection macros.
  • CEL-LANG — official definition of lists, maps, indexing, and conditions.
  • CEL-GO-BIND — official documentation for the optional cel.bind() extension used by the self-contained tab.