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 like 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 like 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 know
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. And 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. And 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 you
know, just like 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 like a lot of
computation that's being wasted. You might not want to
change or run this code block again when let's say 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...
Like this is already pretty helpful for me
but what we can do is like we can make it even better.
So one of the nicer ideas
from these reactive notebooks is this
idea of having an infinite canvas so where you don't look at
the document model you look at the whole
document as like a canvas of multiple connected
documents. So 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, like, let's say if I want to just
have this image shown up at the top let's say, what I can do is
like I can pop this out, which opens a child frame and then I
can just go here. And 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. So the next steps for me are basically making my
workflow easier in matplotlib, which is 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, you know, just JS visualizations.
So yeah, happy to take questions on Etherpad
and thank you for your time.