How do sanitized parameters interact with pure functions in EK9?
← Security and Sanitization · Ref: Q217
In pure functions, sanitized parameters must use the copy constructor pattern because reassignment is forbidden. Purity and security reinforce each other.
PURE + SANITIZED = COPY CONSTRUCTOR
Pure functions cannot reassign, so the only option is:
pureProcess() as pure -> input as sanitized String <- result as String? localCopy <- String(input) result: localCopy
The copy constructor creates an independent value.
WHY THEY INTERACT
Purity prevents mutation, sanitization tracks tainted data. Together they force the safest pattern: create a defensive copy and use only the copy. No escape hatches.
NON-PURE ALTERNATIVES
Non-pure functions have additional options:
safeCopy <- String(input) result: "" result :=: safeCopy // copy operator result :~: safeCopy // merge operator
EXPRESSION USE
Both pure and non-pure can use sanitized parameters directly in expressions:
result: "Prefix: " + input
Concatenation creates a new value, so no aliasing risk.
See Q215 for sanitized basics. See Q54 for pure functions. See Q141 for constant immutability. See Q273 for purity as security boundary.
See Q662 for safe copy patterns. See Q666 for injection pure context.
Example
defines module qa.security.pure defines function // Pure function MUST use copy constructor pureWithSanitized() as pure -> input as sanitized String <- result as String? // Only option in pure context: copy constructor cleanInput <- String(input) result: "Clean: " + cleanInput // Non-pure has more options nonPureWithSanitized() -> input as sanitized String <- result as String? // Option 1: Copy constructor (works everywhere) safeCopy <- String(input) // Option 2: :=: on initialized variable result: "" result :=: safeCopy // Direct expression use works in both contexts directUse() as pure -> input as sanitized String <- result as String? // Concatenation creates new value — safe result: "Output: " + input defines program SanitizedPureDemo() stdout <- Stdout() userInput <- "external input" // === PURE + SANITIZED === result1 <- pureWithSanitized(userInput) if result1? stdout.println(result1) // === NON-PURE + SANITIZED === result2 <- nonPureWithSanitized(userInput) if result2? stdout.println(result2) // === DIRECT EXPRESSION === result3 <- directUse(userInput) if result3? stdout.println(result3) stdout.println("Purity + sanitization = forced defensive copies")
Common mistakes
E50060 — String does not have a copy() method. Use the copy constructor String(value) to create a defensive copy. Calling a non-existent method triggers E50060 — method not resolved. See ek9 -h E50060 for details.
Incorrect:
cleanInput <- input.copy()
Correct:
cleanInput <- String(input)
Other ways to ask this
- Why must pure functions use copy constructors with sanitized parameters?
- How do purity and sanitization work together in EK9?
- What is the copy constructor pattern for sanitized parameters?
Coming from another language?
Java: no purity concept, PreparedStatement for SQL safety. Python: no purity enforcement. Rust: ownership model prevents some aliasing. Go: no purity. Kotlin: no purity. Haskell: purity prevents side effects but no sanitization concept. EK9: purity and sanitization synergize, forcing defensive copy pattern.
Keywords: copy, pure, context, constructor, sanitize, protect, side-effect, defensive, function, immutable, purity, security, safe, sanitized