Scala Collections
Use when scala collections including immutable/mutable variants, List, Vector, Set, Map operations, collection transformations, lazy evaluation with views, parallel collections, and custom collection builders for efficient data processing.
What this skill does
# Scala Collections
## Introduction
Scala's collections library is one of its most powerful features, providing a
rich, unified API for working with sequences, sets, and maps. The library
emphasizes immutability by default while offering mutable alternatives when
needed for performance-critical code.
The collections hierarchy distinguishes between immutable and mutable variants,
with immutable collections being the default. Key collection types include List,
Vector, Set, Map, Array, and their specialized variants. The library provides
consistent transformation operations across all collection types.
This skill covers immutable vs mutable collections, sequences (List, Vector,
Array), sets and maps, collection operations (map, filter, fold), for-comprehensions,
lazy evaluation, parallel collections, and performance characteristics.
## Immutable vs Mutable Collections
Immutable collections provide thread safety and predictability, while mutable
collections offer performance benefits for intensive updates.
```scala
// Immutable List (default)
val immutableList = List(1, 2, 3, 4, 5)
val newList = immutableList :+ 6 // Creates new list
val prepended = 0 :: immutableList // Prepends element
// Original unchanged
println(immutableList) // List(1, 2, 3, 4, 5)
println(newList) // List(1, 2, 3, 4, 5, 6)
// Mutable ListBuffer
import scala.collection.mutable
val mutableList = mutable.ListBuffer(1, 2, 3)
mutableList += 4 // Mutates in place
mutableList ++= List(5, 6)
mutableList -= 2
println(mutableList) // ListBuffer(1, 3, 4, 5, 6)
// Immutable Set
val immutableSet = Set(1, 2, 3)
val addedSet = immutableSet + 4
val removedSet = immutableSet - 2
// Mutable Set
val mutableSet = mutable.Set(1, 2, 3)
mutableSet += 4
mutableSet -= 2
// Immutable Map
val immutableMap = Map("a" -> 1, "b" -> 2, "c" -> 3)
val updatedMap = immutableMap + ("d" -> 4)
val removedMap = immutableMap - "b"
// Mutable Map
val mutableMap = mutable.Map("a" -> 1, "b" -> 2)
mutableMap("c") = 3
mutableMap += ("d" -> 4)
mutableMap -= "b"
// Converting between immutable and mutable
val immutable = List(1, 2, 3)
val asMutable = immutable.toBuffer // Mutable copy
asMutable += 4
val backToImmutable = asMutable.toList
// Immutable Vector (efficient random access)
val vector = Vector(1, 2, 3, 4, 5)
val updatedVector = vector.updated(2, 10) // Efficiently creates new vector
// Choosing between immutable and mutable
// Use immutable for:
// - Default choice
// - Concurrent access
// - Functional transformations
// - Public APIs
// Use mutable for:
// - Performance-critical loops
// - Large-scale updates
// - Local scope only
// - Builder patterns
// Builder pattern with immutable result
def buildList(): List[Int] = {
val builder = List.newBuilder[Int]
for (i <- 1 to 100) {
builder += i
}
builder.result()
}
// Immutable collection with updates
case class User(name: String, age: Int, email: String)
val users = List(
User("Alice", 30, "[email protected]"),
User("Bob", 25, "[email protected]")
)
val updatedUsers = users.map { user =>
if (user.name == "Alice") user.copy(age = 31)
else user
}
```
Prefer immutable collections by default for safety and simplicity, using mutable
collections only when profiling shows performance bottlenecks.
## Sequences: List, Vector, and Array
Different sequence types offer varying performance characteristics for different
access patterns.
```scala
// List: Linked list, O(1) prepend, O(n) random access
val list = List(1, 2, 3, 4, 5)
val prepended = 0 :: list // O(1)
val concatenated = list ::: List(6, 7) // O(n)
val appended = list :+ 6 // O(n)
// Pattern matching on lists
def sumList(list: List[Int]): Int = list match {
case Nil => 0
case head :: tail => head + sumList(tail)
}
// List construction
val range = List.range(1, 11) // List(1, 2, ..., 10)
val filled = List.fill(5)(0) // List(0, 0, 0, 0, 0)
val tabulated = List.tabulate(5)(i => i * i) // List(0, 1, 4, 9, 16)
// Vector: Indexed sequence, O(log32 n) for all operations
val vector = Vector(1, 2, 3, 4, 5)
val vectorUpdated = vector.updated(2, 10) // O(log n)
val vectorAppended = vector :+ 6 // O(log n)
val vectorPrepended = 0 +: vector // O(log n)
// Random access
println(vector(3)) // O(log n) - efficient
// Vector is better for:
// - Random access
// - Both-end operations
// - Large collections
// Array: Mutable, fixed-size, O(1) random access
val array = Array(1, 2, 3, 4, 5)
array(2) = 10 // Mutable update
println(array.mkString(", "))
// Array operations return Arrays
val doubled = array.map(_ * 2)
// ArrayBuffer: Mutable, resizable
import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer(1, 2, 3)
buffer += 4
buffer ++= Array(5, 6)
buffer.insert(0, 0)
buffer.remove(2)
// Seq: General sequence trait
def processSeq(seq: Seq[Int]): Int = seq.sum
println(processSeq(List(1, 2, 3)))
println(processSeq(Vector(1, 2, 3)))
println(processSeq(Array(1, 2, 3)))
// IndexedSeq for efficient random access
def processIndexed(seq: IndexedSeq[Int]): Int = {
var sum = 0
for (i <- seq.indices) {
sum += seq(i)
}
sum
}
// LinearSeq for efficient head/tail operations
def processLinear(seq: collection.LinearSeq[Int]): Int = seq match {
case head :: tail => head + processLinear(tail)
case _ => 0
}
// Range: Lazy, memory-efficient sequences
val range1 = 1 to 10 // 1 to 10 inclusive
val range2 = 1 until 10 // 1 to 9
val range3 = 1 to 100 by 10 // 1, 11, 21, ..., 91
// Stream (deprecated, use LazyList)
val lazyList = LazyList.from(1).take(5)
println(lazyList.toList)
// Choosing the right sequence:
// List - Default, functional style, prepend-heavy
// Vector - Large, random access, both-end operations
// Array - Interop with Java, mutable, performance-critical
// ArrayBuffer - Mutable, frequent updates
```
Choose List for functional programming, Vector for random access, and Array for
Java interop or performance-critical code.
## Sets and Maps
Sets provide unique element storage while maps store key-value pairs, both with
efficient lookup operations.
```scala
// Immutable Set
val set1 = Set(1, 2, 3, 4, 5)
val set2 = Set(4, 5, 6, 7, 8)
// Set operations
val union = set1 union set2 // Set(1, 2, 3, 4, 5, 6, 7, 8)
val intersection = set1 intersect set2 // Set(4, 5)
val difference = set1 diff set2 // Set(1, 2, 3)
// Set methods
println(set1.contains(3)) // true
println(set1(3)) // true (same as contains)
val added = set1 + 6
val removed = set1 - 3
val multiAdd = set1 ++ Set(6, 7, 8)
// Mutable Set
import scala.collection.mutable
val mutableSet = mutable.Set(1, 2, 3)
mutableSet += 4
mutableSet ++= Set(5, 6)
mutableSet -= 2
// Different Set implementations
val hashSet = mutable.HashSet(1, 2, 3) // Unordered, fast
val linkedHashSet = mutable.LinkedHashSet(1, 2, 3) // Maintains insertion order
val treeSet = collection.immutable.TreeSet(1, 2, 3) // Sorted
// SortedSet
val sortedSet = collection.immutable.SortedSet(5, 2, 8, 1)
println(sortedSet) // TreeSet(1, 2, 5, 8)
// Immutable Map
val map = Map(
"Alice" -> 30,
"Bob" -> 25,
"Charlie" -> 35
)
// Map access
println(map("Alice")) // 30
println(map.get("Alice")) // Some(30)
println(map.get("David")) // None
println(map.getOrElse("David", 0)) // 0
// Map operations
val updated = map + ("David" -> 28)
val removed = map - "Bob"
val merged = map ++ Map("Eve" -> 32)
// Map transformations
val ages = map.values.toList
val names = map.keys.toList
val pairs = map.toList
val incremented = map.map { case (name, age) => (name, age + 1) }
val filtered = map.filter { case (_, age) => age > 30 }
// Mutable Map
val mutableMap = mutable.Map("a" -> 1, "b" -> 2)
mutableMap("c") = 3
mutableMap += ("d" -> 4)
mutableMap.update("e", 5)
// Map variants
val hashMap = mutable.HashMap("a" -> 1, "b" -> 2) // Unordered, fast
val linkedHashMRelated in AI Agents
skill-development
IncludedComprehensive meta-skill for creating, managing, validating, auditing, and distributing Claude Code skills and slash commands (unified in v2.1.3+). Provides skill templates, creation workflows, validation patterns, audit checklists, naming conventions, YAML frontmatter guidance, progressive disclosure examples, and best practices lookup. Use when creating new skills, validating existing skills, auditing skill quality, understanding skill architecture, needing skill templates, learning about YAML frontmatter requirements, progressive disclosure patterns, tool restrictions (allowed-tools), skill composition, skill naming conventions, troubleshooting skill activation issues, creating custom slash commands, configuring command frontmatter, using command arguments ($ARGUMENTS, $1, $2), bash execution in commands, file references in commands, command namespacing, plugin commands, MCP slash commands, Skill tool configuration, or deciding between skills vs slash commands. Delegates to docs-management skill for official documentation.
reprompter
IncludedTransform messy prompts into well-structured, effective prompts — single or multi-agent. Use when: "reprompt", "reprompt this", "clean up this prompt", "structure my prompt", rough text needing XML tags and best practices, "reprompter teams", "repromptception", "run with quality", "smart run", "smart agents", multi-agent tasks, audits, parallel work, anything going to agent teams. Don't use when: simple Q&A, pure chat, immediate execution-only tasks. See "Don't Use When" section for details. Outputs: Structured XML/Markdown prompt, quality score (before/after), optional team brief + per-agent sub-prompts, agent team output files. Success criteria: Single mode quality score ≥ 7/10; Repromptception per-agent prompt quality score 8+/10; all required sections present, actionable and specific.
adaptive-compaction
IncludedAdaptive add-on policy and recovery layer that decides WHEN to compact, prune, snapshot, or fork -- replacing fixed-percent auto-compaction across Claude Code, Codex, and MCP-capable hosts. Trigger on auto-compact timing or damage: "when should I compact", "is it safe to compact now or start a fresh session", "auto-compact fires too early/mid-task", "switching to an unrelated task but the window still has space", "context rot", "answers get worse the longer the session runs", "the agent forgot the plan or my decisions after it summarized", "add a layer on top that manages context without changing the agent", raising autoCompactWindow to give the policy room, or installing/tuning a cross-tool compaction policy or PreCompact hook -- even when "compaction" is never said but the problem is context-window pressure or post-summarization memory loss. Do NOT use to summarize a conversation, build RAG, write a summarization prompt (decides WHEN not HOW), or answer max-context-length trivia.
agent-skill-creator
IncludedCreate cross-platform agent skills from workflow descriptions. Activates when users ask to create an agent, automate a repetitive workflow, create a custom skill, or need advanced agent creation. Triggers on phrases like create agent for, automate workflow, create skill for, every day I have to, daily I need to, turn process into agent, need to automate, create a cross-platform skill, validate this skill, export this skill, migrate this skill. Supports single skills, multi-agent suites, transcript processing, template-based creation, interactive configuration, cross-platform export, and spec validation.
llm-wiki
IncludedUse when building or maintaining a persistent personal knowledge base (second brain) in Obsidian where an LLM incrementally ingests sources, updates entity/concept pages, maintains cross-references, and keeps a synthesis current. Triggers include "second brain", "Obsidian wiki", "personal knowledge management", "ingest this paper/article/book", "build a research wiki", "compound knowledge", "Memex", or whenever the user wants knowledge to accumulate across sessions instead of being re-derived by RAG on every query.
skill-master
IncludedAgent Skills authoring, evaluation, and optimization. Create, edit, validate, benchmark, and improve skills following the agentskills.io specification. Use when designing SKILL.md files, structuring skill folders (references, scripts, assets), ingesting external documentation into skills, running trigger evals, benchmarking skill quality, optimizing descriptions, or performing blind A/B comparisons. Keywords: agentskills.io, SKILL.md, skill authoring, eval, benchmark, trigger optimization.