How do I safely access a List element by index?
← Safe Value Access · Ref: Q162
EK9 Lists use getOrDefault(index, default) for safe element access. If the index is within bounds, returns the element. If out of bounds, returns the default. No exceptions.
GETORDEFAULT BY INDEX
Always returns a usable value:
first <- numbers.getOrDefault(0, -1) missing <- numbers.getOrDefault(99, -1)
No IndexOutOfBoundsException, no null, no crashes.
LENGTH CHECK
Check bounds manually when needed:
if length numbers > 0 stdout.println(`Has items`)
EMPTY CHECK
Test whether a list has any elements:
if numbers is empty stdout.println("No items")
SAFE ITERATION
Iterating with for-in never goes out of bounds:
for item in numbers stdout.println($item)
Each item yielded is guaranteed to be set.
STREAM HEAD FOR FIRST ELEMENT
Use head 1 to safely get the first element:
cat numbers | head 1 | collect as List of Integer
Returns an empty list if the source is empty.
See Q45 for List basics. See Q88 for List operations. See Q125 for head/tail/skip in streams.
Example
defines module qa.safeaccess.listsafe defines function getList() <- rtn <- List() of Integer defines program ListSafeAccessDemo() stdout <- Stdout() numbers <- [10, 20, 30, 40, 50] // === GETORDEFAULT BY INDEX === // Valid index — returns element first <- numbers.getOrDefault(0, -1) stdout.println(`First: ${first}`) third <- numbers.getOrDefault(2, -1) stdout.println(`Third: ${third}`) // Out of bounds — returns default outOfBounds <- numbers.getOrDefault(99, -1) stdout.println(`Out of bounds (default -1): ${outOfBounds}`) // === LENGTH CHECK === listLen <- length numbers stdout.println(`Length: ${listLen}`) if length numbers > 0 stdout.println("List has items") // === EMPTY CHECK === emptyList <- getList() if emptyList is empty stdout.println("Empty list detected") if ~numbers is empty stdout.println("Numbers is not empty") // === SAFE ITERATION === for item in numbers stdout.println(`Item: ${item}`) // === STREAM HEAD FOR FIRST ELEMENT === firstItems <- cat numbers | head 1 | collect as List of Integer stdout.println(`Head 1: ${firstItems}`) // Head on empty list yields empty result noItems <- cat emptyList | head 1 | collect as List of Integer stdout.println(`Head of empty: ${noItems}`)
Common mistakes
E50060 — List has no get(index) method that could throw on invalid indices. Use getOrDefault(index, default) which always returns a usable value. This prevents IndexOutOfBoundsException-style bugs. See ek9 -h E50060 for details.
Incorrect:
first <- numbers.get(0)
Correct:
first <- numbers.getOrDefault(0, -1)
E50060 — List has no elementAt() method. Use getOrDefault(index, default) which always returns a usable value. See ek9 -h E50060 for details.
Incorrect:
third <- numbers.elementAt(2)
Correct:
third <- numbers.getOrDefault(2, -1)
Other ways to ask this
- How do I avoid index out of bounds in EK9?
- What is the safe way to get an element from a List in EK9?
- How do I access list elements without exceptions in EK9?
Coming from another language?
Java: list.get(index) throws IndexOutOfBoundsException if out of bounds. Python: list[index] throws IndexError, negative indices wrap. Rust: vec[index] panics, vec.get(index) returns Option. Go: slice[index] panics if out of bounds. Kotlin: list[index] throws, list.getOrElse(index) { default } is safe. EK9: getOrDefault(index, default) always returns a value, no exceptions.
Keywords: array, default, element, exception, list, bounds, access, index, getOrDefault, guard, null-safe, safe