Ladder Of Abstraction
Notes from reading Up and Down the Ladder of Abstraction ↗ by Bret Victor.
-
real-time makes sense for things that need to be watched in real-time (like an animation)
- sometimes it makes sense to not be limited by this - when editing movie for example, you don't want to keep watching the entire film in real-time, but scrub freely through it
- to explore a system like that, you need to be able to control its time
-
the same way we scrub through time we should be able to scrub through variables
-
then, we can abstract over time - draw a path of what something will look like, and change the variables to see the path change, without having to scrub through it
-
then, we can then abstract over time and a parameter - drawing all possible behaviours of the algorithm
the purpose of abstraction is to bring out high-level patterns
We stepped up a level of abstraction to see a high-level pattern, and then stepped down to discover the explanation for that pattern. I believe that this dance is where the deepest insights are born - not at any one level of abstraction, but in the transitions between them. This is why it is crucial that our representations provide both a step up and a step back down.
-
-
when abstracting, it's ok to omit some details to gain better understanding of the system
-
interaction is important part of abstraction - being able to interact with the visualization (and see other visualizations change) helps us build mental model of the solution space (Solving Things Visually)
- human brains are good at matching visual patterns, but slow (and bad) at logical inferences
- it makes sense to turn these inferences into visual representations, so we can reason about them with our visual side of brain
- it makes sense to be able to play with them to gain even better understanding of them - static visualization is not enough, interaction with living system combined with visualization is important
-
how this relates to programming:
- "concrete" representation:
function f() { const t = 100; const r = 2; const [x, y] = calculate(t, r); return [x, y]; } - abstracting over time:
function f(t) { const r = 2; const [x, y] = calculate(t, r); return [x, y]; } - abstracting over time and rate:
function f(t, r) { const [x, y] = calculate(t, r); return [x, y]; } - "stepping down" the ladder when we found interesting
ris currying:const f_of_2 = t => f(t, 2);
- "concrete" representation: