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
filter()finds the active candidate Maya.- The helper map is
{'matches': [{'name': 'Maya', 'active': true}]}. size() > 0is true, so access tomatches[0]is safe.- 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
- Run the prepared expression.
- Set
active: falsefor both candidates. - Remove the
size() > 0guard and try to readstate.matches[0].namedirectly.
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 optionalcel.bind()extension used by the self-contained tab.