Clojure Keynote
From JVMLangSummit
Jump to navigationJump to search
Contents
Provocation
- Is OOP the best way to write software?
Background
- single-dispatch, stateful, OOP languages are entrenched
- differences between these languages are superficial (ex: syntax, availability of closures, etc.)
- key ideas: complexity, time
- "Seek simplicity, and distrust it." - Whitehead
Incidental Complexity
- bad tools and solutions make us less efficient in small ways
- complexity is obvious, but sometimes complexity is hidden behind a facade of simplicity
- C++ is easy to learn, but is it really simple?
- same syntax to refer to things on the heap and things not on the heap
- what do you do with objects? no standard automatic memory management - big source of incidental complexity
- the language doesn't make it clear that memory management is the programmer's responsibility
- ditto Java
- even removes the complexity of handling GC
- hidden complexity: mutable vs immutable objects; not just a concurrency problem, a complexity problem
- most programmers measure complexity in superficial ways: syntax, expressivity
- we want encapsulation so we can build things on top of other things more simply; "someone building a house doesn't have to worry about the inside of a brick"
Pure Functions Are Worry-Free
- local scope
- takes and returns values
- has no notion of time
- easy to understand and change
- problems with functions, though:
- "programs in general are not functions"
- programs run indefinitely long
- users need to see the program's behavior
- couldn't express Google search as a function, it's a process
OO and Change
- behavior and time are almost meaningless in OOP
- there's no real concept of time in objects, they don't have a reified notion of time, but objects pretend to manipulate time
- "the OO model has gotten time wrong"
- we've made objects that can change in place, and we've made objects that we can _see_ change in place
- no proper notion of values
- "No man can cross the same river twice."
A Simplified View
- "We've invented mutable objects, we need to un-invent them."
- actual entities are atomic immutable values
- we superimpose mutable models on collections of immutable values
- identities are mental constructs
- the future is a function of the past
- objects are not things that change over time
- "There is a becoming of continuity, but not a continuity of becoming."
Terms
- Value: immutable magnitude, quantity, number, or immutable composite thereof
- Identity: a relative entity we associate with a series of values
- State: value of an identity at a moment in time
- "mutable state makes no sense (given this definition)"
- Time: relative before/after ordering of causal values
Why should we care?
- our programs need to make decisions
- mutable way of thinking is a useful mental model, makes things easier to conceptualize
- but we can't screw up time and immutability because then things are wrong
- we don't make decisions about the world through direct contact between our brains and the outside world - we don't take our brains out and rub them on things we want to experience
- we also don't get to stop the world to look around
- human perception is uncoordinated and massively parallel - it's NOT message passing
- we are always perceiving the unchanging past
- we perceive based on discrete events - we like snapshots (they're like values)
- are brains are simultaneity detectors
- making things happen are perceiving things are completely different
Implementation
- pure functions - we have this
- language constructs for representing values, creating them and sharing them
- coordinate the succession of values
- we have to consume memory to model time
- old value -> pure function -> new value (non-destructive, consumes memory)
- old values can be used as perceptions/memory
- GC will clean up the "past" that's no longer referenced
- persistent data structures
- immutable
- ideal for states, snapshots, and memories
- stable values for decision-making and calculation
- the next version of a value shares structure with previous value, so usually efficient
- creating a value never disturbs prior values, nor impedes perceivers of prior
- "your life is going to be better if you use these because there's a huge quantity of things you'll no longer have to worry about"
- usually based on trees (with high branching factors, usually shallow)
- support structural sharign
Declarativeness and Parallelism
- must be more declarative, less looping
- tree-based persistent data structures work well for this
- pre-partitioned
- compositional building blocks
- don't perform as well - better for reads than write, but...
- nobody can see what happens inside operations
- more cores, and the parallelism starts to match up to mutable data structures
Time Constructs
- need to ensure atomic succession
- need to provide point-in-time value perception (snapshots)
- multiple timelines support multiple threads of control - no "I'm the program, I control the universe" model
- models: CAS, Agents, STM, locks as a way to enforce timelines
- perception in STM via multi-version concurrency control
- no interference with processes
- cheap historical snapshots
- allows observers/readers to maintain a timeline
- composite snapshots form glimpses and visual scans, thinking in terms of human vision
- "there is no one STM; if you want to beat up on STM, pick an implementation"
- granularity matters; if you find yourself requiring a transaction to perceive a consistent value, you're doing it wrong
Conclusion
- excessive implicit complexity begs for change
- conflation of behavior, time, identity, and state is a big source of implicit complexity in OOP
- "pay attention to the FP people, look at the great properties of pure functions"
- epochal time model is worth trying - be explicit about time
- we can do multiple implementations, we have the infrastructure to support it
- hard problems: tying STM to things like IO, coordinating with the rest of the world
- "become as happy as you can with the lack of control - that will give you more concurrency"
- more data structures and time constructs to come
- open question: is there a way to reconcile all this with OOP?