Purity Enforcement & Impure Functions
Relevant source files
The following files were used as context for generating this wiki page:
Jazz is designed as a functional language where functions are pure by default. To manage side effects, the language distinguishes between pure and impure functions through explicit syntax and compiler-level enforcement. This system ensures that side effects are predictable and isolated, drawing inspiration from languages like Haskell and Elixir.
Sources: README.md:10-12, README.md:108-112
Core Purity Principles
In Jazz, purity is the baseline for all function declarations. A pure function is one that returns a value based solely on its inputs and has no observable side effects. Impure functions, which may perform I/O or modify state, are treated as distinct entities by the compiler.
Purity by Default
Every function declared via a lambda assignment is considered pure unless explicitly marked otherwise. This pure-by-default stance allows the compiler to perform aggressive optimizations and ensures code reliability.
Sources: README.md:108-110
The Bang Operator (!)
Impurity is explicitly denoted using the ! suffix. This operator is mandatory for any function that performs side effects. For example, standard I/O functions like print! and getLine! must include this suffix in their identifiers.
Sources: README.md:112-115
| Syntax Element | Description | Example |
|---|---|---|
\(args) -> ... | Pure lambda declaration. | isEven = \(i) -> mod(i, 2) == 0 |
name! | Impure function identifier. | println! "Hello" |
! Suffix | Required for impure function names. | greet! = \(n) -> { ... } |
Sources: README.md:116-125
Enforcement Mechanisms
The Jazz compiler, specifically within the jazz-next/ implementation path, applies rules to prevent the accidental or unauthorized use of impure code within pure contexts.
Stub Purity Enforcement
The current compiler implementation (v1) utilizes "stub purity enforcement." This mechanism specifically checks for direct calls to "!"-suffixed callees within the bodies of bindings that are not themselves marked as impure.
Sources: README.md:19-20, README.md:110-112
Dependency Hierarchy
The following diagram illustrates the relationship between the analyzer and the enforcement of purity during the compilation process.
The Analyzer.hs module is responsible for binding/signature coherence and initial purity validation, while the Driver.hs manages the propagation of these semantic errors into the final compile results.
Sources: jazz-next/README.md:18-28
Impure Function Constraints
Impure functions are subject to specific structural and usage constraints:
- Call Restriction: An impure function cannot be called from within a pure function body. This is the primary gatekeeping mechanism for maintaining purity.
- Naming Convention: All identifiers for impure functions must end with the
!character. - Explicit Body: While pure functions often use single-line expressions, complex impure functions typically utilize curly braces for multiline logic, such as sequencing I/O operations.
Sources: README.md:108-125
Example: Side-Effect Sequencing
Impure functions allow for the sequential execution of side-effecting operations, such as reading from standard input and then printing a formatted string.
// Impure function using multiline braces
greet! = \(ignored) -> {
name = getLine!.
println!("Hello, ${name}").
}.
Sources: README.md:123-127
Future Effects System
While the current version of Jazz uses direct-call enforcement (stub-v1), the project roadmap includes a transition to a "full effect typing" system. This planned advancement will move beyond simple identifier checks to a more robust type-level representation of side effects, similar to algebraic effects or monadic types in other functional languages.
Sources: README.md:110-112, README.md:27-28
Summary
Purity enforcement in Jazz provides a clear boundary between logic and side effects. By requiring the ! suffix for impure functions and providing stub enforcement in the jazz-next compiler, the system ensures that developers must be explicit about where side effects occur. This architecture supports the project's goal of creating a functional language that is both powerful and accessible to those intimidated by more complex category-theory-oriented type systems.
Sources: README.md:7-12, jazz-next/README.md:1-5