WEBVTT

00:00.000 --> 00:07.000
Hi, can everybody hear me?

00:07.000 --> 00:08.000
Yes.

00:08.000 --> 00:09.000
Okay, great.

00:09.000 --> 00:10.000
Hi, everybody.

00:10.000 --> 00:12.000
My name is Dave Thompson.

00:12.000 --> 00:14.000
I am the CTO at the Sprite Institute.

00:14.000 --> 00:18.000
And today, we're talking about functional reactive programming with propagators.

00:18.000 --> 00:20.000
Words you may or may not understand.

00:20.000 --> 00:21.000
Don't worry.

00:21.000 --> 00:22.000
I will explain them.

00:22.000 --> 00:26.000
But quickly, about Sprite Lee, Christine already explained, but working on the next generation

00:26.000 --> 00:27.000
of you centralized technology.

00:27.000 --> 00:31.000
So I probably won't belabor the point since Christine was just here.

00:31.000 --> 00:33.000
So let's get right into it.

00:33.000 --> 00:36.000
Before we get to the functional aspect, let's just talk about reactive programming.

00:36.000 --> 00:41.000
Who knows what knows what it is or has used a library for active programming.

00:41.000 --> 00:42.000
Okay.

00:42.000 --> 00:43.000
Little over half of the room I'd say.

00:43.000 --> 00:44.000
Okay.

00:44.000 --> 00:49.000
For those that don't know, the way I like to describe it is it's a way to work with time varying values

00:49.000 --> 00:52.000
without entering callback health.

00:52.000 --> 00:57.000
So without having to do like procedural event driven continuation passing style programming.

00:57.000 --> 01:01.000
So it's usually as a declarative abstraction.

01:01.000 --> 01:04.000
Sorry, abstraction on top of an event loop.

01:04.000 --> 01:10.000
So like in the web browser, you know, you have events for keyboard input, mouse input, etc.

01:10.000 --> 01:14.000
Rather than writing event callbacks, you have some declarative ways to do this.

01:14.000 --> 01:20.000
Graphical user interfaces are kind of where this type of programming seems to be used the most.

01:20.000 --> 01:23.000
And probably if I say the word react.

01:23.000 --> 01:26.000
Does everyone know what react is?

01:26.000 --> 01:27.000
Show of hands.

01:27.000 --> 01:28.000
Okay, basically.

01:28.000 --> 01:29.000
Okay, yeah.

01:29.000 --> 01:31.000
So react really means streamed.

01:31.000 --> 01:35.000
Reactive programming for like the web development community at large.

01:35.000 --> 01:36.000
So here's an example.

01:36.000 --> 01:39.000
Probably the simplest example from the react documentation.

01:39.000 --> 01:41.000
It's just a button.

01:41.000 --> 01:44.000
And then every time you click it, the click increments.

01:44.000 --> 01:47.000
So this is reactive, but it's not functional.

01:47.000 --> 01:50.000
So I want to talk about the functional side.

01:50.000 --> 01:55.000
At it's simplest, we just take reactive programming and then we use more peer functions.

01:55.000 --> 01:57.000
And we have function active programming.

01:57.000 --> 02:02.000
However, it's really hard to define FRP without probably making somebody mad.

02:02.000 --> 02:05.000
Because it's not a super well-defined term.

02:05.000 --> 02:07.000
And there's no way we can do that.

02:07.000 --> 02:10.000
It's really hard to define FRP without probably making somebody mad.

02:10.000 --> 02:13.000
Because it's not a super well-defined term.

02:13.000 --> 02:16.000
And there seems to be contention about what it really means.

02:16.000 --> 02:17.000
There's many forms.

02:17.000 --> 02:23.000
There's a continuous FRP, discrete FRP, push-based pull-based hybrid push-pull-based.

02:23.000 --> 02:38.000
But for this talk, I'm just going to say that discrete push-based FRP seems to be the most practical thing for dealing with things like just the event loops that we're typically used to.

02:38.000 --> 02:40.000
So I'm going to go with that.

02:40.000 --> 02:43.000
And this is not a new idea.

02:43.000 --> 02:47.000
This is a paper from ICFP in 1997 called Functional Reactive Animation.

02:47.000 --> 02:51.000
And I believe this is the origin of the term Functional Reactive programming.

02:51.000 --> 02:56.000
This was implemented in Haskell way back when.

02:56.000 --> 03:03.000
And I believe the authors of this paper would probably be mad about the definition of FRP that I just told you.

03:03.000 --> 03:06.000
So hopefully they're not ever going to see this.

03:07.000 --> 03:13.000
Unlike React, which is immensely popular, FRP has not had the same success of React likes.

03:13.000 --> 03:17.000
And I like to think of this blog post from the L language.

03:17.000 --> 03:22.000
If anyone's familiar with L, it was like a Haskell like that ran in the compiled JavaScript ran.

03:22.000 --> 03:23.000
But I was still around.

03:23.000 --> 03:27.000
But I had a big moment in the early-to-mid, you know, 2010s.

03:27.000 --> 03:29.000
And it went all in on FRP at the beginning.

03:29.000 --> 03:34.000
And then in 2016, they wrote this, the creator Evan wrote a farewell to FRP.

03:34.000 --> 03:42.000
And I kind of like to, to me, this is kind of like the death now of of FRP as like an idea that was gaining like.

03:42.000 --> 03:46.000
It was gathering steam and then it kind of, I feel like a kind of died here.

03:46.000 --> 03:53.000
But I, this FRP bug has been in my brain for longer than this and it's never really left.

03:53.000 --> 03:54.000
I keep being interested in it.

03:54.000 --> 03:59.000
And so never mind all that stuff, you know, maybe all these projects tried and failed.

03:59.000 --> 04:02.000
Let's, let's look at this with scheme.

04:02.000 --> 04:05.000
So here's a really wonderful, amazing demo.

04:05.000 --> 04:06.000
It was very complicated.

04:06.000 --> 04:09.000
And you see it's the same thing as in the React code that I showed you.

04:09.000 --> 04:11.000
Little button, I click in an increments. Oh, great.

04:11.000 --> 04:14.000
Well, that's amazing. Okay, talk over.

04:14.000 --> 04:19.000
What I'm going to show is, I'll show you some scheme code.

04:19.000 --> 04:24.000
So don't worry too much about understanding this, but I want to show that it's declarative and functional.

04:24.000 --> 04:28.000
In the sense that we, you're not going to see a set bang here or any kind of mutation.

04:28.000 --> 04:32.000
We, we have this, I'm calling themselves a, they hold time-bearing values.

04:32.000 --> 04:36.000
This one's going to hold click notifications.

04:36.000 --> 04:41.000
Concepts that we're used to in functional programming are like doing operations on list, map pretty well.

04:41.000 --> 04:45.000
So we're going to fold and it's a fold not over a list, but over time.

04:45.000 --> 04:47.000
We're going to take in the click cell.

04:47.000 --> 04:51.000
We're going to have an initial value of zero because the initially the user hasn't clicked the button at all.

04:51.000 --> 04:55.000
And every time an event comes in, we're going to modify that kind of, we're going to increment it.

04:55.000 --> 04:59.000
And then good thing Christine was just talking about SXML.

04:59.000 --> 05:01.000
This is the next SXML template.

05:01.000 --> 05:05.000
And what we do is we have an on-click handler here.

05:05.000 --> 05:07.000
And we got this on-quote thing.

05:07.000 --> 05:09.000
We turn this click cell.

05:09.000 --> 05:10.000
We make a listener for it.

05:10.000 --> 05:16.000
So every time a click event comes in, we update our little FRP cell.

05:16.000 --> 05:18.000
And then we splat in the count.

05:18.000 --> 05:22.000
And so this refers to the value of the cell.

05:22.000 --> 05:26.000
The engine behind all of this just ensures that the UI is updated.

05:26.000 --> 05:33.000
And so this presentation that I've been showing you is running the web browser is running a scheme program.

05:33.000 --> 05:35.000
This is the source code for the slide you just saw.

05:35.000 --> 05:41.000
So this is a web assembly program that is a scheme program called the web assembly running these slides.

05:41.000 --> 05:44.000
So this is the actual code of the demo I just showed you.

05:44.000 --> 05:48.000
So we'll go back to the presentation.

05:48.000 --> 05:50.000
I think I have to click off of here.

05:50.000 --> 05:52.000
Okay.

05:52.000 --> 05:56.000
So I can't talk about FRP without talking about glitches.

05:56.000 --> 05:59.000
I can't really talk about reactive programming general without talking about glitches.

05:59.000 --> 06:05.000
The most important job of any reactive library or framework is to avoid glitches.

06:05.000 --> 06:16.000
And a glitch is usually a brief small, like tiny moment of time, where a time varying value gets computed with a mix of scale and fresh data.

06:16.000 --> 06:20.000
And it becomes often becomes user visible and it's like a flash of something weird.

06:20.000 --> 06:24.000
And it comes in it goes, but it leads to like a janky user experience.

06:24.000 --> 06:26.000
And we don't want this.

06:26.000 --> 06:29.000
So I'm going to try to walk through this little thing.

06:29.000 --> 06:32.000
I can explain glitches with just a graph of four nodes.

06:32.000 --> 06:37.000
So right here, it's just a very simple data flow graph.

06:37.000 --> 06:39.000
A is the root.

06:39.000 --> 06:40.000
Numbers enter here.

06:40.000 --> 06:42.000
I'm just going to be working with integers.

06:42.000 --> 06:44.000
And so it gets any time A changes.

06:44.000 --> 06:45.000
We take A times two.

06:45.000 --> 06:46.000
We put it in B.

06:46.000 --> 06:47.000
Take A plus one.

06:47.000 --> 06:48.000
Put it in C.

06:48.000 --> 06:51.000
And then D depends on both B and C and we just take the difference.

06:51.000 --> 06:54.000
And so at the start, the cells contain nothing.

06:54.000 --> 06:57.000
We have to bootstrap our graph.

06:57.000 --> 07:01.000
So somehow we insert the number two and that kicks off reactivity.

07:01.000 --> 07:04.000
So it flows to B.

07:04.000 --> 07:05.000
And we double it.

07:05.000 --> 07:06.000
So we get four.

07:06.000 --> 07:07.000
We add one.

07:07.000 --> 07:08.000
We get three.

07:08.000 --> 07:10.000
And then finally we take the difference and we get one.

07:10.000 --> 07:11.000
Great.

07:11.000 --> 07:12.000
All looks well.

07:12.000 --> 07:16.000
However, let's take another another approach to it.

07:16.000 --> 07:18.000
Another data flow path.

07:18.000 --> 07:20.000
So we come in at the root again bootstrap.

07:20.000 --> 07:22.000
We update this value to three.

07:22.000 --> 07:26.000
We propagate to to node B.

07:26.000 --> 07:27.000
We double it.

07:27.000 --> 07:28.000
We get six.

07:28.000 --> 07:32.000
But instead of going to node C, we go to node D.

07:32.000 --> 07:35.000
Node D depends on B and C.

07:35.000 --> 07:37.000
So we take the difference and we get three.

07:37.000 --> 07:38.000
But that's wrong.

07:38.000 --> 07:41.000
Because the value here is three.

07:41.000 --> 07:44.000
So what we really want is the value two.

07:44.000 --> 07:49.000
But because this cell refreshed before this one, we have a glitch.

07:49.000 --> 07:54.000
And so eventually, after two more steps, converges to the correct value.

07:54.000 --> 08:00.000
But we have a moment that's probably going to annoy a user somewhere in the interface where the value is wrong.

08:00.000 --> 08:02.000
So this is no good.

08:02.000 --> 08:04.000
How do we avoid glitches?

08:05.000 --> 08:09.000
Reactive libraries typically do something like a topological sort.

08:09.000 --> 08:13.000
So D is below nodes B and C in the graph.

08:13.000 --> 08:16.000
So B and C should be refreshed first and then D.

08:16.000 --> 08:20.000
And then we ensure that D is always computed with fresh values.

08:20.000 --> 08:22.000
But we have a restriction.

08:22.000 --> 08:24.000
Once we add that property.

08:24.000 --> 08:27.000
The node graph must be a cyclic.

08:27.000 --> 08:30.000
And only, and therefore as a consequence,

08:30.000 --> 08:39.000
only a subset of possible interfaces that we can implement with event callbacks are now expressable with reactive programming or functional reactive programming.

08:39.000 --> 08:43.000
So it turns out.

08:43.000 --> 08:45.000
We will be able to remove this restriction.

08:45.000 --> 08:47.000
But I want to show an example.

08:47.000 --> 08:50.000
So this is a color picker diagram.

08:50.000 --> 08:54.000
Here we have the RGB values for representing color that way.

08:54.000 --> 08:58.000
And then on the other side we have a hue saturation value.

08:58.000 --> 08:59.000
Sliders.

08:59.000 --> 09:03.000
And what we would like to have happen is any time you manipulate one of these sliders.

09:03.000 --> 09:05.000
The sliders over here change.

09:05.000 --> 09:09.000
So we convert RGB to HSV and update the sliders accordingly.

09:09.000 --> 09:12.000
And when you change any of the HSV values.

09:12.000 --> 09:16.000
We convert HSV to RGB and update these.

09:16.000 --> 09:18.000
So there's circularity there.

09:18.000 --> 09:20.000
Like you see in the middle.

09:20.000 --> 09:25.000
And so we can't express that with acyclic reactivity.

09:25.000 --> 09:28.000
But acyclic reactivity is the norm.

09:28.000 --> 09:30.000
And it's what is popular.

09:30.000 --> 09:36.000
And it seems like what's going to continue to be used in the industry at large.

09:36.000 --> 09:39.000
This is a screenshot of a TC39 proposal.

09:39.000 --> 09:42.000
The standards group responsible for changes to JavaScript.

09:42.000 --> 09:44.000
They're working on something called signals.

09:44.000 --> 09:47.000
And it's a proposal for one way data flow in JavaScript.

09:47.000 --> 09:54.000
And it's going to be a reactive libraries in JavaScript to bring an API to JavaScript itself.

09:54.000 --> 09:57.000
But so that's the state of the art there.

09:57.000 --> 10:01.000
But I wouldn't be up here if I thought cyclic reactivity was impossible.

10:01.000 --> 10:02.000
It's very possible.

10:02.000 --> 10:05.000
And the secret ingredient is propagators.

10:05.000 --> 10:07.000
Has anyone heard of propagators?

10:07.000 --> 10:08.000
Okay.

10:08.000 --> 10:12.000
Much smaller group of people than new about reactivity in general.

10:12.000 --> 10:19.000
So I want to introduce you to one of my favorite PhD dissertations, which I feel is a weird thing to say.

10:19.000 --> 10:22.000
Because who has a list of their favorite ones.

10:22.000 --> 10:25.000
Normally they're so dense they're hard to read.

10:25.000 --> 10:27.000
I got to trust me on this.

10:27.000 --> 10:28.000
This one isn't.

10:28.000 --> 10:31.000
This is by Alexei Raduel, who was a PhD student MIT.

10:31.000 --> 10:33.000
This is from 2009.

10:33.000 --> 10:37.000
Propagation networks, a flexible and expressive substrate for computation.

10:37.000 --> 10:38.000
It is a fantastic read.

10:38.000 --> 10:43.000
I'm going to cover just a little tiny bit of that paper that talks about FRP.

10:43.000 --> 10:47.000
And no more, but I really recommend if any of this peaks your interest.

10:47.000 --> 10:48.000
Go there.

10:48.000 --> 10:52.000
Everything I'm about to tell you is derived from it.

10:52.000 --> 10:54.000
So what the hell are propagators?

10:54.000 --> 10:55.000
This is a lot of text.

10:55.000 --> 10:56.000
I'll just read the bold part.

10:56.000 --> 11:02.000
There are autonomous independent machines interconnected by shared cells through which they communicate.

11:02.000 --> 11:09.000
And this is straight out of Gerald Susman's and I'm forgetting the co-author right now.

11:09.000 --> 11:12.000
But software design for flexibility from 2021.

11:12.000 --> 11:19.000
If you liked SICP and you want something similar to it that's not from the 80s with additional more advanced topics,

11:19.000 --> 11:22.000
check that book out MIT press.

11:22.000 --> 11:23.000
Okay.

11:23.000 --> 11:26.000
So in real simple terms, cells are nodes.

11:26.000 --> 11:30.000
But notably they contain partial information.

11:30.000 --> 11:35.000
This is Alexa Redwell's key insight in his dissertation.

11:35.000 --> 11:38.000
You can including partial information being nothing.

11:38.000 --> 11:44.000
So there's initially a cell contains nothing and over time it accumulates information.

11:44.000 --> 11:47.000
And this can get particularly complicated.

11:47.000 --> 11:55.000
A lot of propagator, lore and research goes into AI systems and like truth, maintenance systems and stuff.

11:55.000 --> 11:58.000
I'm going to talk about something much simpler.

11:58.000 --> 12:00.000
You can get pretty crazy.

12:00.000 --> 12:02.000
And the propagators you can just think of as the edges.

12:02.000 --> 12:06.000
They're the things that take values from some input cells.

12:06.000 --> 12:09.000
Just some computation and then write them to one or more output cells.

12:09.000 --> 12:13.000
But notably this relationship between cells can be one to one.

12:13.000 --> 12:14.000
It can be one to what many.

12:14.000 --> 12:15.000
It can be many to many.

12:15.000 --> 12:20.000
There's no restriction on that.

12:20.000 --> 12:27.000
And also there's no restriction on when propagators like fire and when they refresh themselves.

12:27.000 --> 12:34.000
So propagator flow is dumb and it's dumb on purpose to meant to be very easy to implement.

12:34.000 --> 12:41.000
And so propagator networks by definition, they have no order of evaluation and they have no directionality restrictions.

12:41.000 --> 12:47.000
So if we want to build reactivity on propagators, we can't do topological sort.

12:47.000 --> 12:49.000
So we have to do something else.

12:49.000 --> 12:50.000
So we have a problem.

12:50.000 --> 12:55.000
If we don't solve the problem, we're going to have glitches and we're going to have a terrible reactive system.

12:56.000 --> 13:05.000
So as is often the case, there's a lot of things in computer science where you start with some kind of unordered system and you put order on top of it.

13:05.000 --> 13:07.000
Well, propagators are no different.

13:07.000 --> 13:14.000
I'll actually write a dual-explained that using an approach that really resembles logical timestamps in a distributed system.

13:14.000 --> 13:19.000
If you're familiar with logical clocks, transport timestamps, vector clocks, very similar concept.

13:19.000 --> 13:32.000
What we want to do is when we bootstrap our nodes, when data comes into it from the outside world somewhere, we want to make sure that each piece of data is tagged with some kind of unique identifier for each piece of data.

13:32.000 --> 13:39.000
And then some kind of logical timestamp, that's increasing monotonically with each change.

13:39.000 --> 13:46.000
And so as values accumulate and flow through the graph, you'll get many such pairs and these pairs form a vector clock.

13:46.000 --> 13:54.000
And with that, you can tell if the data that you're about to use is fresh or not.

13:54.000 --> 14:04.000
And so we can halt propagation when when a propagator fires and it discovers that its inputs have differing timestamps for the same identifier.

14:04.000 --> 14:08.000
One says that the time was one when this value came in and the other was two.

14:08.000 --> 14:20.000
That's conflicting. We have old and new mixed together. We should stop right there. We need to wait in order to actually do the transformation that we want to do so we halt.

14:20.000 --> 14:25.000
And that enables circularity without infinite loops.

14:25.000 --> 14:36.000
And so the trade-off here is that there is a bit of redundant computation because a propagator may fire when it can't actually do anything yet and it has to stop and it has to know that.

14:36.000 --> 14:42.000
So versus topological sort, you kind of visit each node and you know it's ready to go.

14:42.000 --> 14:47.000
But the total amount of redundant computation is actually quite minimal.

14:47.000 --> 14:57.000
And so without any ordering guarantees, a much simpler substrate, much simpler infrastructure, we can still get the same properties that we want values that converge without glitches.

14:58.000 --> 15:07.000
And so my definition of FRP on propagators is that it's the propagation of a femoral values. A femoral values are things that change over time.

15:07.000 --> 15:15.000
And so in my prototype implementation there is a type of record type and scheme is just called a femoral.

15:15.000 --> 15:18.000
It's a box that has any arbitrary value.

15:18.000 --> 15:26.000
And then on the side it has a set of sources. It's the vector clock. It has all the information from once that value came, you know.

15:26.000 --> 15:33.000
It's derived from these identifiers at these particular points in logical time.

15:33.000 --> 15:36.000
And that is enough to get what we need.

15:36.000 --> 15:45.000
I want to make a quick note. I mentioned this earlier, but it's not just I showed a fold earlier, but pretty much any list processing idiom translates really well to FRP.

15:46.000 --> 15:50.000
You're just not mapping over a set of pairs. You're mapping over time.

15:50.000 --> 15:55.000
So map, fold, filter. You get the idea. All these things, you know, map pretty naturally.

15:55.000 --> 16:02.000
So as a functional programmer or a scheme programmer or a list programmer that's used to these things, I think you can get with it pretty quick.

16:02.000 --> 16:07.000
So let's go back to the color picker. You know, I showed this graph earlier.

16:07.000 --> 16:10.000
And I wouldn't show it if we couldn't do it.

16:10.000 --> 16:22.000
And here it is. So this is running in the slide. This is actually code that's using propagators running in the hoot scheme interpreter, which has been compiled to web assembly and running in the browser here.

16:22.000 --> 16:32.000
So you see as as I adjust the sliders in the RGB, the HSV side changes and we have the little color swatch up there to tell you what it is and the hex code if you want to copy it out in some other application.

16:32.000 --> 16:37.000
And here I am changing Q saturation and value and the RGB sliders go.

16:37.000 --> 16:47.000
So yeah, it works and don't just take my word for it.

16:47.000 --> 16:53.000
I mean, I guess you have to also take my word that this is real code that runs and I didn't just do smoke and mirrors on you.

16:53.000 --> 17:02.000
But this is kind of, I'm going to have a hard time with the resolution of this fitting it in a single page.

17:02.000 --> 17:15.000
But just to show you, I've been working on some syntax that's not very good right now to define recursive graphs of notes.

17:15.000 --> 17:29.000
And so here are the values that become our sliders. We have the RGB group and as RGB and then HSV group HSV one thing I haven't talked about is what the heck is this group.

17:30.000 --> 17:39.000
Turns out that so RGB those are three facets of the same object like they they compose together to form an RGB expression of color.

17:39.000 --> 17:48.000
And so what we want is that all three of these, they have the same identifier and they share the same timestamp counter.

17:48.000 --> 17:56.000
So when you change any one of those you're changing this identifier that becomes the RGB group.

17:56.000 --> 18:02.000
You know it starts at zero and change R goes to one you change B it goes to two they're linked together.

18:02.000 --> 18:14.000
And that proves to be an essential part of making the propagation work so essentially facets of of a composite object that are at the root of your reactive graph.

18:14.000 --> 18:23.000
You you generally you want to make sure that they are using the same logical time and they're kind of understood as like one machine in the system.

18:23.000 --> 18:33.000
If that didn't make sense don't don't worry too much about it and then finally my kind of work in progress terrible notation for.

18:33.000 --> 18:47.000
The edges in the graph if you've ever used the dot notation and graph is it's like a kind of a list be version of that, but I'm just saying that Rg and B those cells combine.

18:47.000 --> 18:54.000
To write a value to the RGB cell and RGB color is a constructor for an RGB color record.

18:54.000 --> 19:16.000
But it's bi-directional so when RGB changes we destructure the record and we put the RGB values in their corresponding cells the same thing applies to HSV just with the HSV record and it's it's accessors and then the the good stuff happens here it's just a this is a bi-directional expression of when HSV changes.

19:16.000 --> 19:24.000
We convert it to RGB and we write it to the RGB cell when RGB changes we convert it to HSV and put it in the HSV cell.

19:24.000 --> 19:32.000
So that's like the that's the that's the entire propagator network really and then all that's left to do is hook it up to a UI.

19:32.000 --> 19:38.000
And let's see if I can get it all I can get it mostly on one screen.

19:38.000 --> 19:43.000
The top it doesn't really matter we we have some procedures to convert an RGB color to a hex train.

19:43.000 --> 19:49.000
I'm just like jet splatting out some gross CSS there for the color swatch and then again we have.

19:49.000 --> 19:55.000
This is the slide that I just showed you this is the record type for these slides in the the slideshow system.

19:55.000 --> 20:01.000
And another quasi quote and so another SXML template and then I have some helpers to do the sliders for me but notably.

20:01.000 --> 20:12.000
There's Rgb I'm referring to these cells and the rendering engine will hook things up such that there it does all the callback stuff under the hood.

20:12.000 --> 20:21.000
So there's a slider and the sliders have a value anytime the cell changes it'll it'll call it'll update the value of the dom node for that slider.

20:21.000 --> 20:28.000
And anytime someone slides it that value will then get placed into the cell as an updated value and then the propagation starts.

20:28.000 --> 20:34.000
So this is how values enter the propagation graph and the graph is bootstrapped.

20:34.000 --> 20:44.000
But it's a two way binding so so if you're used to two way binding for many other web UI framework it's it's the same thing but just expressed in a in a different way.

20:44.000 --> 20:51.000
So yeah, that's the basics of the of the code and I am close to done here.

20:51.000 --> 20:54.000
I just wanted to show you that just so future work.

20:54.000 --> 21:07.000
I cobbled this together pretty fast before for them I had done I wrote a blog post about this in 2024 and then I kind of just stopped doing anything with it and I kind of refreshed it for this talk.

21:07.000 --> 21:19.000
And so I did a lot of re-implementation of things and it's kind of a mess but it works but it's not optimal there's a lot of places that are slow so to make this actually usable from scheme.

21:19.000 --> 21:28.000
In real programs that are not just demos I'd like to optimize internal algorithms to make the propagation better and generate less garbage.

21:28.000 --> 21:37.000
So we run the garbage collector less frequently which could lead to UI junk you know the be a bad experience with the GC's running all the time.

21:37.000 --> 21:44.000
And I'd like to publish a library that works for both the guy virtual machine and also on the web for who I mean I mostly want to use this for web UI's.

21:44.000 --> 21:53.000
And then I'd like to actually test drive it in some of the demos that we do it sprightly we've been wanting some kind of UI framework for a while and since we we use scheme.

21:53.000 --> 22:01.000
As Christine was saying it's a great thing for doing all of our experimentation but on the other hand the flip side is that you end up rolling your own stuff a lot of the time.

22:01.000 --> 22:08.000
So you know I don't I don't want to use reactive you or anything like that I want I want to use our scheme thing so I want to try it out there.

22:08.000 --> 22:16.000
So that's really it you know I do all this with sprightly if you like what we do at all where if I want to see three my profit.

22:16.000 --> 22:24.000
You know we can't do the work we do without help from from you all so please spread the Institute slash donate.

22:24.000 --> 22:31.000
If you become a recurring donor we will shout you out on our on like every blog post we do I plug.

22:31.000 --> 22:37.000
I check out our donations list and I thank everybody that's that's got monthly donations set up in there on our various tiers.

22:37.000 --> 22:45.000
So anyway we greatly appreciate your support support I'm done thank you do we have time for questions.

22:45.000 --> 22:52.000
Like clapping for myself over here I don't understand.

22:52.000 --> 22:57.000
Okay let's see I'll start here.

22:57.000 --> 23:09.000
The question was in my demo I have this arrow operator and what is that.

23:09.000 --> 23:16.000
It's it's a syntax literal it's just used to separate the inputs from the outputs because the.

23:16.000 --> 23:23.000
I just needed some notation to show that it's like values are flowing from the left to the right.

23:23.000 --> 23:26.000
It's it's not no so I just wrote.

23:26.000 --> 23:34.000
This is what needs development like we need I need an ergonomic like domain specific language for doing this and in the very little time I had.

23:34.000 --> 23:40.000
I thought of just using what graph is does and you just do a little arrow.

23:40.000 --> 23:48.000
Yeah yeah yep so it's I could show you the macro after it's kind of it's it's trash to be honest with you but.

23:48.000 --> 23:53.000
Yeah I think it's like approximately something that you would want but like without the arrow.

23:53.000 --> 24:00.000
It looks like this and it's like if you're reading that it's like how do I know that I don't know what that's doing like if I read it like.

24:00.000 --> 24:07.000
But with the arrow looks like okay values are flowing from the left to the right so that's just kind of the intent that I wanted to put behind this syntax.

24:07.000 --> 24:09.000
But it's just a literal there.

24:10.000 --> 24:11.000
Thank you.

24:11.000 --> 24:12.000
Okay.

24:12.000 --> 24:16.000
Still like in this piece of code.

24:16.000 --> 24:22.000
Yeah like in this case the propagator doesn't execute like each individual function like.

24:22.000 --> 24:28.000
It goes a little signed a value one at a time or sort of happens like.

24:28.000 --> 24:32.000
The group gets a reassign all in what's because it's a group right.

24:32.000 --> 24:39.000
Yeah so for the groups what happens is when a cell is updated like said the R cell gets updated.

24:39.000 --> 24:46.000
As part of it it looks at all the members of its group and it calls the special thing to fresh in the timestamp on it.

24:46.000 --> 24:55.000
So it doesn't propagate that value from those other cells but it does ensure that it knows about the timestamp going up.

24:55.000 --> 24:58.000
So they just have to all have the same notion of logical time.

24:58.000 --> 25:09.000
And if and if they do then the propagation works if if that didn't happen the problem becomes that there's a lot of redundant computation that happens if they if they're not like synced up in that way.

25:09.000 --> 25:13.000
I don't think I can explain that in a succinct way right now.

25:13.000 --> 25:14.000
Yeah.

25:14.000 --> 25:15.000
Okay yeah welcome.

25:15.000 --> 25:17.000
Let's see oh all the way in the back.

25:17.000 --> 25:18.000
Yeah.

25:18.000 --> 25:19.000
I think that is up at the end.

25:19.000 --> 25:21.000
Look at the air sometimes here.

25:21.000 --> 25:23.000
I was here is.

25:23.000 --> 25:31.000
So I specifically like the form of classic pepperoni from like the little alien.

25:31.000 --> 25:35.000
There's continuous time and simple formal semantics.

25:35.000 --> 25:37.000
And the distinction of the people here is an event.

25:37.000 --> 25:42.000
Yeah where does your implementation relate to this.

25:43.000 --> 25:49.000
Do you have a similar model of like the semantics which operators supposed to do here.

25:49.000 --> 25:54.000
I think the distinction or is our things grouped together more.

25:54.000 --> 25:58.000
Let's see okay the question was about if.

25:58.000 --> 26:00.000
If I'm used if or.

26:00.000 --> 26:09.000
Hmm how do we even say the question about continuous FRP semantics versus discrete semantics I think was the core of the question.

26:09.000 --> 26:10.000
Sorry.

26:10.000 --> 26:13.000
Did I get that roughly right I.

26:13.000 --> 26:15.000
Yeah it does not exist.

26:15.000 --> 26:19.000
So I'll just I think the short answer is it's not classic FRP.

26:19.000 --> 26:21.000
I have not gone the continuous route.

26:21.000 --> 26:27.000
I've gone for discrete event based things because we're used to discrete event based systems.

26:27.000 --> 26:30.000
And it seems like the fastest way to get something that works.

26:30.000 --> 26:35.000
But I'm also I've never used a continuous FRP system.

26:35.000 --> 26:38.000
So it could be that I'm just ignorant.

26:38.000 --> 26:42.000
And I need some exposure to that to know what I could take from it.

26:42.000 --> 26:45.000
So do you have any recommendations I would love to hear.

26:45.000 --> 26:48.000
Yeah thank you for your question.

26:48.000 --> 26:49.000
Yeah.

26:49.000 --> 26:52.000
I'm explaining which is you mentioned that.

26:52.000 --> 26:56.000
When resolving two values for different time exams you have to stop the date.

26:56.000 --> 26:57.000
Yes.

26:58.000 --> 27:14.000
So the question was why not just use the freshest value if there's a mix of the two.

27:14.000 --> 27:22.000
And in the general case there could be many things that are not fresh about it.

27:22.000 --> 27:25.000
There could be more than one.

27:25.000 --> 27:31.000
And it's not you're not guaranteed you could have two stale values actually for the same thing.

27:31.000 --> 27:36.000
And that would also result in a glitch because it may be maybe some third that maybe some third input

27:36.000 --> 27:38.000
Propagated over there.

27:38.000 --> 27:44.000
So like you know add a fifth node to the graph and that one updated and you still have stale data.

27:44.000 --> 27:48.000
So I think in the general case it's tough maybe there's an optimization.

27:48.000 --> 27:51.000
So I've just went the dumb way that I know works.

27:51.000 --> 27:52.000
Yeah.

27:53.000 --> 27:55.000
I think that's is that it for questions.

27:55.000 --> 27:57.000
We could take it outside or.

27:57.000 --> 27:59.000
Well okay I will be we can hallway track it.

27:59.000 --> 28:01.000
Happy to answer questions outside.

