Hello, everyone. My name is Abhinav,
and I'm going to talk about
how to make Org Babel reactive. So reactivity here
means reactivity in the sense of reactive notebooks.
So if you used Org Babel,
you might also have used Jupyter notebooks,
which are basically notebooks primarily for
Python programming,
where you have these text and code blocks interleaved,
and then you can execute every code block independently,
and then you control the order of execution manually,
or you can just run the code blocks
from top to bottom. But with reactive notebooks,
what happens is that there's another way of running
which is basically by having all these
dependent code blocks automatically get
executed whenever you make a change.
So for example, if you change a variable,
everything else that's dependent on
that variable will be executed automatically.
I'll show you an example of what that looks like.
Right, here's an example reactive Notebook.
So this is called Observable.
Observable is this tool made by
the creator of d3.js which is
a famous JavaScript charting library. So here, the
interface is very similar to Jupyter Notebook.
You basically are having these cells
and each cell could be a text cell, like here,
this is a Markdown cell
and then there are these code blocks.
Now each code cell is basically defining a variable.
This is important in reactive notebooks because
each cell is connected to other cell via this variable
usage. So here data is defined,
then there is filtered which is defined
which is dependent on data, and then this plot is
dependent on filtered.
So now, in a classical notebook, what I will do is
if I change something here, let's say from 1 to 2,
I will have to run this, and then run this plot block again
to make the change be visible.
But in a reactive notebook, what happens is
I can just change this from some value
to some value, and then execute,
and then every descendant is also executed,
because that's how the reactivity works.
You change this variable,
so this should also be changed,
because this is dependent on this variable.
Now this is really helpful
if you have a very complex and messy notebook
which is what actually happens in reality.
You end up doing an exploratory analysis,
and you have these code blocks lying here and there.
Then you change something
and then you have to keep something in your mind
that if I change this, I need to run
these five code blocks again
to finally get to the result that I want to see.
Stale state causes a lot of issues in Jupyter Notebooks.
So this is really good for reactivity, sorry reproducibility,
but this is also really good for
just having this exploration
that you're trying to do. For example,
you're changing something and it's really easy
to just see that change happening in real time
in your outcome variables, right?
So I was wondering how to introduce this reactivity in Org Mode.
And here's how it will look like.
So this is a demo Org Mode file.
There are many Org Babel blocks here.
So you start from here.
Let's say this is a code block. It has a name.
And then there's another code block,
which is dependent on the previous one,
as you can see here, and so on.
And then finally, there's a plot here,
which is a gnuplot code.
And you can see the image here.
Now, what happens usually is that
if I change this value from,
let's say, 113 to 112, nothing happens on its own right?
There's an extra step of execution that I will have to do
so I will do that, and then the value is changed.
Now the problem is that only this value is changed and
if I go down and see the image, nothing will have changed.
So what I can do is basically,
a really simple thing is that,
a simple trick is to basically
enable a hook, like, add a hook
whenever you're saving the buffer,
you just run the full buffer again,
like run all the code blocks automatically.
Now if you do that, you can basically make a change somewhere
and then you can, you know,
see how everything else is changing
which gives you some sort of reactivity,
but there's still a lot of computation
that's being wasted.
You might not want to change or run this code block again
when something down there is changing.
So to counter that, you can actually add caching.
So if you add caching to any code block,
that code block will only be executed again
if that code has changed or
the input variables have changed.
But the other problem is that
you don't want caching to be enabled for a lot of cases
where the code block is actually dependent on
external state, like for example,
some sort of randomness or time.
So caching also is, you know, kind of,
it's, like, an important thing to use,
but it's probably not giving you the complete answer.
So what we can instead do is basically figure out
the whole computation dependencies here.
So let's say if I look at this buffer,
here's how all the blocks are connected.
So as you can see the plot code block
is dependent on c and then legendpg,
and they themselves are dependent on these other nodes.
So when I make a change in b, I only want b to run
and then c and then plot. I don't want anything else to run.
So what I did was I wrote a small minor mode for Org Mode
which does exactly this.
So whenever you are in a code block
and you are making a change and then you save it,
it will just follow the trail from that code block
to every other descendant which is going to be impacted,
and it just runs all of them, and nothing else gets executed.
So to see it in action, I will just enable that mode.
Yeah, right. So now here, if I change this 113 to 112
and I save, this code, this variable gets changed.
It's the same value because I did not update it again.
And you can also see b also got changed
because it's just following all the execution order and so on.
The plot also got updated.
We will be able to see more clearly
once I change something more substantial.
So here's another variable.
So I added a small toggle button here,
which is again part of the minor mode.
So since this is nil, if I toggle it,
it will become true. And this variable dictates whether
the plot will have the legend or not.
So if I toggle it to be t, now it's t
and you can see that the plot has legend that's visible.
If I toggle it back again to nil, the legend is gone.
Now this is nice, this...
This is already pretty helpful for me
but what we can do is we can make it even better.
So one of the nicer ideas
from these reactive notebooks
is this idea of having an infinite canvas
where you don't look at the document model,
you look at the whole document
as a canvas of multiple connected documents.
One good thing that happens there is that
you can basically have a piece of code somewhere
and then piece of code
somewhere very different position in the document,
but you can put them together in the canvas
and then see them side by side.
So here also, let's say
if I want to just have this image shown up at the top,
what I can do is like I can pop this out,
which opens a child frame, and then I can just go here.
This child frame is showing the same image.
So there's no change. So if I toggle this variable here,
you can see that the image is updated.
If I toggle it back to nil, the image, the legend is gone.
And you can obviously, you know,
you can make a lot of things come up as child frames.
This is the same image.
So even if you go down to the document,
you will see the same image.
So yeah, this is what I have right now.
I'm definitely looking forward to making it more useful,
probably including more kinds of child frames,
maybe like making the whole document an infinite canvas.
Alright, so that's the talk.
If you're interested in the codebase,
here's the homepage
for the project [https://dev.lepisma.xyz/git/ob-rx].
So the next steps for me are basically
making my workflow easier in matplotlib,
which is a Python-based library,
and d3.js, which is for JavaScript.
For the JS thing, I might have to add
the interactive JS child frames,
and I am also looking forward to building something
which can replicate the work
of the Observable's infinite canvas,
because that's something
which I found really useful in my work with
just JS visualizations.
So yeah, happy to take questions on Etherpad
and thank you for your time.