We all love immutability in Clojure.
So why not make Clojure environment (including namespaces etc.) into an immutable value?
Approach:
- Environment is a persistent data structure. Something like a map of maps (Environment->namespaces->vars)
- "def" becomes an operation that produces a new Environment
- In the REPL not much changes: you always work on the latest Environment.
- You can resolve symbols in an Environment, which becomes an explicit parameter rather than an implicit global state.
- Code can read *environment* to get the current Environment for a thread.
- With liberal use of *environment* as a default, code that doesn't rely on mutating the environment can (probably?) run unchanged.
Some potential advantages:
- Simpler?
- Better aligned with Clojure's philosophy. Usual advantages of immutable values.
- Code can be "isolated" with different environments, e.g. different app server contexts.
- We can "snapshot" a running program Environment for later use / analysis
- Environment updates could be made transactional. Anyone have a use for this?
- Threads have their own environments (a better alternative to binding?)
- A secure sandbox can be implemented with a reduced Environment
- Test code can run in a mocked-out Environment
- Allows for roll-back of Environment state (useful at the REPL?)
- Environments are merge-able (basis for a module system with concurrent loading?)
- Lazy/concurrent compilation probably becomes feasible (a big boost to Clojure startup time?)
- Probably simplifies issues with code reloading
- Probably simplifies static analysis / type checking
Some downsides:
- A fair bit of work, obviously.
- Doesn't change the fact that you can store mutable things in the environment (atoms etc.)
- New semantics for lots of things. Though might be possible to coexist with / emulate old semantics.
- Almost certainly breaks stuff
- Represents major language design change - Clojure 2.0 territory at least
Thoughts?
Is this a possible extension to Clojure, or is this a completely new language?