Capture to see
One reason why programming can be considered "hard" is the fact that programs by definition are build on abstractions. As much power as abstractions can bring: they can make it harder to actually see what happens in programs.
Take the object-oriented concept of classes as an example. A class serves as a description of objects*. First when a class gets instantiated it produces an actual thing whose state can be inspected and whose behavior observed. One big contribution of the Self language was to show how much more direct and straightforward programming becomes when prototypical inheritance (no abstract classes anymore) is paired with tools that allow to directly interact with objects.
No matter which programming methodology you subscribe to, the programming language and the tools you use should make it easy for you to understand and see what happens in the programs you write. Playing interpreter is not our strong side, computers are much better at that!
* Even if your programming language has first-class classes (as it should).
Capturing Clojure state with cloxp
One feature of cloxp is to instrument expressions and capture the values they produce over time. In its essence this is actually not more than libraries like tools.trace or spyscope provide. However, building this feature into a rich environment such as the one cloxp provides allows
a) to easily instrument multiple locations and arrange the gathered data in a way that allows to compare it and to stay on top of things
b) to access the gathered data directly, for example to inspect it further
Here is how it works. Inside a function you select a sub expression for capturing. From that point on a small annotation that appears on all views of that function will show the last value that was captured:
By clicking on that annotation (or invoking a shortcut of you are a keyboard junkie) you can open up another workspaces that shows the captured values. Note that the captured data is still there, you can directly evaluate and inspect it:
This also works for asynchronous code:
(Note, by default only the last 30 captures are stored, this number can be increased if necessary.)
The feature is "real" and not just meant for the playground; it is no problem to instrument system-level code and code across namespaces. Ever wanted to see what's really going on in your Clojure image? Just ask it!
(Note, the function instrumented below is clojure.main/repl which itself is used continuously by cloxp, even (de)instrumenting depends on it. Yet, no interruption occurs.)
In order to stay on top of things you can get a summary of all captures:
Capturing values is one of the simplest ways to help you see what is actually happing in your code. By being able to directly access captured state you can directly find out what data your code deals with, making debugging much faster and direct and allowing you to peek through layers of abstractions. Paired with some support around visualization, managment and inspection it is a tool that will make the term "printf debugging" hopefully extinct.