Status
Accepted
Context
Slug supports immutable data structures and favors structural updates over mutation.
Structs already support immutable update semantics through the copy keyword:
val next = user copy {
age: 43
}
However, maps currently rely on lower-level update functions such as:
val next = put(config, :timeout, 5000)
This creates an inconsistency in how immutable updates are expressed across structurally similar data types.
The inconsistency becomes more pronounced in a dynamically typed language where values are frequently data-shaped and may originate from:
- JSON payloads
- ACP messages
- configuration maps
- structs
- module exports
- runtime metadata
This distinction is also difficult for AI-assisted code generation systems, which strongly benefit from uniform transformation semantics.
Decision
The copy keyword SHALL support both structs and maps.
copy represents a type-preserving immutable structural update operation.
Examples:
val nextUser = user copy {
age: 43
}
val nextConfig = config copy {
timeout: 5000
}
Struct Semantics
When used with structs, copy SHALL:
- preserve the original struct type
- validate updated fields
- reject unknown fields
- return a new struct instance
Example:
val next = user copy {
age: 43
}
Map Semantics
When used with maps, copy SHALL:
- preserve the map type
- apply key updates as a shallow structural merge
- allow arbitrary keys
- return a new map instance
Example:
val next = config copy {
timeout: 5000,
retries: 3
}
Shallow Copying
copy SHALL always perform shallow structural updates.
Nested values are reused unless explicitly replaced.
Example:
val next = state copy {
user: state.user copy {
active: true
}
}
Unsupported Types
copy is not supported for primitive scalar values.
Attempting to use copy with unsupported types SHALL produce a runtime error.
Example:
42 copy {
value: 99
}
Design Philosophy
copy expresses semantic intent:
- derive a new value from an existing value
- preserve immutability
- minimize representational variance across data types
This aligns with Slug’s broader language goals:
- explicit immutable state transitions
- structurally readable code
- minimal special cases
- AI-friendly semantics
Consequences
Positive
- Unifies immutable update semantics across structs and maps
- Reduces cognitive overhead in dynamically typed code
- Improves readability by emphasizing transformation intent over update mechanics
- Reduces representational variance for AI-assisted code generation
- Reinforces immutable programming patterns
- Keeps structural updates visually consistent across the language
- Avoids introducing additional update keywords or merge syntax
Negative
copysemantics differ slightly between structs and maps- Runtime type validation remains necessary for struct updates
- Some users may initially expect deep copy behavior
Neutral
put()and related map functions remain valid lower-level primitivescopycontinues to represent shallow structural updates only- Future composite types may optionally adopt
copysemantics