How do I merge two lists or two dicts in EK9?
← Common Collection Tasks · Ref: Q186
EK9 provides the :~: merge operator for in-place merging and the + operator for creating new merged collections.
LIST MERGE (:~:)
Append all items from source to target:
target :~: source
Modifies target in place.
LIST PLUS (+)
Create a new combined list:
combined <- list1 + list2
Both originals unchanged.
DICT MERGE (:~:)
Merge never overwrites a set value; it fills whatever is unset or missing, key by key:
target :~: source
A key the target lacks is added, a value the target holds unset is filled, and a value the target holds set is KEPT - the first recorded value wins. Nested dicts are merged by the same rule.
DICT PLUS (+)
Create a new merged dict:
combined <- dict1 + dict2
With +, where keys overlap the right-hand dict's value is used.
COPY (:=:)
Copy one collection into another:
target :=: source
Replaces the target contents entirely with the source's elements. The copy is shallow: the elements themselves are shared with the source, not duplicated.
See Q88 for List operations. See Q90 for Dict operations. See Q130 for mutating vs non-mutating operators.
Example
defines module qa.collectiontasks.mergecollections defines program MergeCollectionsDemo() stdout <- Stdout() // === LIST MERGE (:~:) === list1 <- [1, 2, 3] list2 <- [4, 5, 6] list1 :~: list2 stdout.println(`List merge: ${list1}`) // === LIST PLUS (+) === left <- [10, 20] right <- [30, 40] combined <- left + right stdout.println(`List +: ${combined}`) stdout.println(`Left unchanged: ${left}`) // === DICT MERGE (:~:) === d1 <- {"a": 1, "b": 2} d2 <- {"b": 99, "c": 3} d1 :~: d2 //b was already set in d1, so it keeps 2; c was missing, so it is added stdout.println(`Dict merge: ${d1}`) // === DICT PLUS (+) === base <- {"x": 10} extra <- {"y": 20, "z": 30} merged <- base + extra stdout.println(`Dict +: ${merged}`) stdout.println(`Base unchanged: ${base}`) // === COPY (:=:) === source <- [100, 200, 300] target <- List() of Integer target :=: source stdout.println(`Copied list: ${target}`) srcDict <- {"key": 42} tgtDict <- Dict() of (String, Integer) tgtDict :=: srcDict stdout.println(`Copied dict: ${tgtDict}`) // === MERGE SINGLE ITEM === names <- ["Alice", "Bob"] names :~: "Charlie" stdout.println(`After merge single: ${names}`)
Common mistakes
E50060 — EK9 uses the :~: merge operator for in-place collection merging, not an addAll() method. See ek9 -h E50060 for details.
Incorrect:
list1.addAll(list2)
Correct:
list1 :~: list2
E50060 — EK9 uses the :~: merge operator for merging Dict entries, not a putAll() method. Unlike putAll(), a key the target already holds set keeps its value - only missing keys and unset values are filled. See ek9 -h E50060 for details.
Incorrect:
d1.putAll(d2)
Correct:
d1 :~: d2
Other ways to ask this
- How do I combine two collections in EK9?
- What is the EK9 equivalent of addAll() or putAll()?
- How do I join or concatenate two lists in EK9?
Coming from another language?
Java: list.addAll(other), map.putAll(other), no operator syntax. Python: list.extend(other), dict.update(other), | for dict union. Rust: vec.extend(other), map.extend(other). Go: append(slice1, slice2...), manual loop for maps. JavaScript: [...arr1, ...arr2], Object.assign(). Kotlin: list + other, map + other. EK9: :~: merge operator (never overwrites a set value - for a Dict it is closer to putIfAbsent() than putAll()), + for new combined collection, :=: to replace the target's contents with the source's elements (a shallow copy).
Keywords: merge, dict, join, combine, append, collection, copy, union, list, concatenate, task