WEBVTT captioned by sachac, checked by sachac
NOTE Introduction
00:00:02.120 --> 00:00:07.399
Hello and welcome everyone on EmacsConf 2023.
00:00:07.400 --> 00:00:08.719
I'm Andrew Tropin.
00:00:08.720 --> 00:00:11.919
I work on operating systems and programming languages.
00:00:11.920 --> 00:00:16.639
Today, we discuss Lisps, Schemes, REPLs,
00:00:16.640 --> 00:00:18.139
interactive development,
00:00:18.140 --> 00:00:23.279
and how to make your own cozy development environment.
NOTE Interactive development
00:00:23.280 --> 00:00:26.319
Let's start from interactive development.
00:00:26.320 --> 00:00:29.519
Lisps are famous for a nice
00:00:29.520 --> 00:00:32.479
Interactive Development Experience.
00:00:32.480 --> 00:00:33.999
They have REPLs.
00:00:34.000 --> 00:00:40.119
Emacs Lisp has its own Lisp machine,
00:00:40.120 --> 00:00:44.719
and a lot of cool IDE with different functionality
00:00:44.720 --> 00:00:47.879
is already here and providing
00:00:47.880 --> 00:00:51.619
a nice and pleasant experience.
00:00:51.620 --> 00:00:56.839
The question is, is it enough?
00:00:56.840 --> 00:00:59.920
In most cases, yes, but for some languages,
00:00:59.921 --> 00:01:04.839
we have some white spaces, some missing pieces.
00:01:04.840 --> 00:01:08.299
And for example, in Scheme world,
00:01:08.300 --> 00:01:10.879
we already have a few tools.
00:01:10.880 --> 00:01:14.599
We have REPL, we have integration for REPL in Emacs,
00:01:14.600 --> 00:01:16.679
but is it enough?
00:01:16.680 --> 00:01:18.179
Let's see.
NOTE REPL: Read Eval Print Loop
00:01:18.180 --> 00:01:22.839
We know that Emacs is very good for Lisps and REPL.
00:01:22.840 --> 00:01:26.039
Lisp and Emacs should be a perfect setup.
00:01:26.040 --> 00:01:30.079
But let's see how REPL basically works.
00:01:30.080 --> 00:01:34.799
It's an event loop which does three things.
00:01:34.800 --> 00:01:37.279
It reads an expression, it evaluates the expression,
00:01:37.280 --> 00:01:40.739
and it prints the result.
00:01:40.740 --> 00:01:47.279
We can take a simple expression, input it into REPL,
00:01:47.280 --> 00:01:48.959
and evaluate it and see the result.
00:01:48.960 --> 00:01:50.819
Very nice, very convenient.
00:01:50.820 --> 00:01:55.339
You can experiment and see immediately what is happening.
00:01:55.340 --> 00:01:57.759
You can even run a long-running process
00:01:57.760 --> 00:01:58.919
which does something.
00:01:58.920 --> 00:02:07.199
You can interrupt it and everything will be okay.
00:02:07.200 --> 00:02:08.639
But the problem appears
00:02:08.640 --> 00:02:11.659
when you start to develop a bigger project.
00:02:11.660 --> 00:02:14.039
And in most cases, you don't do
00:02:14.240 --> 00:02:16.399
your whole development in REPL.
00:02:16.400 --> 00:02:18.460
You do only a small part of it.
00:02:18.461 --> 00:02:20.679
In most cases, you just write
00:02:20.680 --> 00:02:22.919
the source code in text files,
00:02:22.920 --> 00:02:26.399
and after that, you run those snippets of code
00:02:26.400 --> 00:02:30.520
from those text files, or run the whole project.
00:02:30.721 --> 00:02:33.719
It's not very convenient to copy and paste
00:02:33.720 --> 00:02:36.039
every time the snippets of code to the REPL,
00:02:36.040 --> 00:02:38.879
see the result, modify the snippet of code,
00:02:38.880 --> 00:02:41.199
copy it again, and so on.
00:02:41.200 --> 00:02:44.039
So people invented some integration
00:02:44.040 --> 00:02:46.079
between REPL and your text editor.
00:02:46.080 --> 00:02:51.599
So you can evaluate expressions inside your text editor
00:02:51.600 --> 00:02:53.719
and see the result here.
NOTE Long-lasting loops
00:02:53.720 --> 00:02:56.679
Works good so far, but what happens
00:02:56.680 --> 00:03:02.299
if we run a long-lasting loop,
00:03:02.300 --> 00:03:04.999
which does a lot of operations.
00:03:05.000 --> 00:03:07.839
As you can see here with a simple example,
00:03:07.840 --> 00:03:13.599
the output of the function,
00:03:13.600 --> 00:03:16.759
stdout of the function is presented here,
00:03:16.760 --> 00:03:18.799
and the resulting value is here.
00:03:18.800 --> 00:03:22.359
If you run a long-running process,
00:03:22.360 --> 00:03:24.639
you don't see anything happening.
00:03:24.640 --> 00:03:29.259
And you see there's a watch instead of my cursor.
00:03:29.260 --> 00:03:33.719
Maybe you don't see it, but nothing actually happens,
00:03:33.720 --> 00:03:36.379
at least from the point of view of the user.
00:03:36.380 --> 00:03:38.399
But if we interrupt the evaluation,
00:03:38.400 --> 00:03:41.439
we will see that some process in the background
00:03:41.440 --> 00:03:44.239
was launched, but we didn't see anything.
00:03:44.240 --> 00:03:51.039
Because the REPL is a single-threaded blocking process,
00:03:51.040 --> 00:03:54.319
which reads stdin and prints stdout,
00:03:54.320 --> 00:03:55.679
make the integration
00:03:55.680 --> 00:03:58.540
between the REPL and your text editor
00:03:58.541 --> 00:04:02.919
is not an easy task.
00:04:02.920 --> 00:04:04.320
And even if you do it,
00:04:04.321 --> 00:04:07.599
you have a lot of downsides, usually.
NOTE Not interruptible
00:04:07.600 --> 00:04:13.679
First of all, the process is not interruptible.
00:04:13.680 --> 00:04:18.479
If you have a remote process which listens on the socket
00:04:18.480 --> 00:04:21.939
to which you connect from your development environment,
00:04:21.940 --> 00:04:25.479
and you run some infinite loop, for example,
00:04:25.480 --> 00:04:28.299
you can't interrupt it.
00:04:28.300 --> 00:04:31.239
Because interruption is done via signals,
00:04:31.240 --> 00:04:35.039
and signals to remote processes are not usually
00:04:35.040 --> 00:04:38.759
the thing in such integrations.
NOT Output is not interactive
00:04:38.760 --> 00:04:41.159
Output is also not interactive.
00:04:41.160 --> 00:04:45.319
Usually, for example, here you can see
00:04:45.320 --> 00:04:47.799
when I evaluate the expression,
00:04:47.800 --> 00:04:51.119
the output is captured on the evaluation side,
00:04:51.120 --> 00:04:53.719
and after that, after the whole evaluation
00:04:53.720 --> 00:04:56.179
of the whole expression finished,
00:04:56.180 --> 00:05:06.759
I get the result, all the stdout at once.
00:05:06.760 --> 00:05:09.919
And if I run the process which evaluates for 5 seconds,
00:05:09.920 --> 00:05:13.780
I will see the first signs of the life
00:05:13.781 --> 00:05:17.039
only after 5 seconds of evaluation.
00:05:17.040 --> 00:05:23.159
Okay, what else?
NOTE No protocol
00:05:23.160 --> 00:05:26.119
When you do such integrations, you have no protocol,
00:05:26.120 --> 00:05:29.759
you have just stdin and stdout.
00:05:29.760 --> 00:05:32.919
You print to stdin from your text editor.
00:05:32.920 --> 00:05:36.679
You read from stdout of the process.
00:05:36.680 --> 00:05:40.339
It's hard to tell if evaluation is finished,
00:05:40.340 --> 00:05:47.319
if it requires stdin, and how to extend the REPL
00:05:47.320 --> 00:05:51.479
to make it more featureful, and so on.
NOTE Not scalable
00:05:51.480 --> 00:05:57.359
And also, such integrations are usually not very scalable.
00:05:57.360 --> 00:06:14.699
For example, if you want to have a completion,
00:06:14.700 --> 00:06:17.460
you type something, you have the completion. Cool.
00:06:17.461 --> 00:06:22.039
But if you run the process and at the same time
00:06:22.040 --> 00:06:24.620
try to have a completion, you don't have it,
00:06:24.621 --> 00:06:29.799
because the evaluation is in progress,
00:06:29.800 --> 00:06:33.279
and you can't calculate the completion candidates
00:06:33.280 --> 00:06:35.519
at the same time. To make it more obvious,
00:06:35.520 --> 00:06:41.019
I will start a completion here.
00:06:41.020 --> 00:06:43.279
You see the completion pop-ups.
00:06:43.280 --> 00:06:46.159
I start the evaluation process,
00:06:46.160 --> 00:06:49.859
and when I try to complete something,
00:06:49.860 --> 00:06:53.119
the evaluation freezes and there is no completion.
00:06:53.120 --> 00:06:55.479
Not very convenient.
00:06:55.480 --> 00:06:58.119
Usually, you have some long-running processes
00:06:58.120 --> 00:07:01.399
and you want them to continue while you have
00:07:01.400 --> 00:07:08.579
your go to definition, completion, and other things.
00:07:08.580 --> 00:07:13.659
Overall, those issues make it quite inconvenient
00:07:13.660 --> 00:07:18.419
to integrate REPL in text editors or development environments,
00:07:18.420 --> 00:07:21.379
so you need something else
00:07:21.380 --> 00:07:25.859
to make the work comfortable.
NOTE nREPL
00:07:25.860 --> 00:07:28.979
There is already a solution called nREPL.
00:07:28.980 --> 00:07:31.119
It's a synchronous protocol which allows
00:07:31.120 --> 00:07:34.019
to send operations to the server
00:07:34.020 --> 00:07:37.759
and receive responses in a synchronous manner.
00:07:37.760 --> 00:07:42.159
And here is a simple example of a few operations.
00:07:42.160 --> 00:07:45.079
First one is cloning the existing session,
00:07:45.080 --> 00:07:49.240
and as a response you will get a new session.
00:07:49.241 --> 00:07:52.099
Also you send the evaluation request with code
00:07:52.100 --> 00:07:55.639
that you want to evaluate, and you get two responses.
00:07:55.640 --> 00:08:00.600
First one says that output is captured
00:08:00.601 --> 00:08:02.839
and it's equal to "hi\n",
00:08:02.840 --> 00:08:06.560
and after that, you receive an "Evaluation completed",
00:08:06.561 --> 00:08:12.439
the value of this expression.
00:08:12.440 --> 00:08:14.079
This protocol was developed
00:08:14.080 --> 00:08:15.879
for CIDER development environment.
00:08:15.880 --> 00:08:18.759
It's a Clojure development environment for Emacs.
00:08:18.760 --> 00:08:22.859
It's very cool, featureful, reliable,
00:08:22.860 --> 00:08:26.899
and I would say production-ready.
00:08:26.900 --> 00:08:31.499
A lot of professional Clojure developers use it.
00:08:31.500 --> 00:08:33.239
The nREPL protocol is very simple.
00:08:33.240 --> 00:08:38.219
It has a few operations out of the box,
00:08:38.220 --> 00:08:46.479
and you can extend it with any arbitrary operation you want.
00:08:46.480 --> 00:08:53.819
I work a lot on Guix codebase and other Scheme projects,
00:08:53.820 --> 00:08:57.299
so the experience I had previously with nREPL
00:08:57.300 --> 00:08:59.399
was not satisfying. I decided
00:08:59.400 --> 00:09:01.739
to just implement nREPL protocol.
NOTE Arei, Ares, and how to try
00:09:01.740 --> 00:09:05.719
First of all, I implemented nREPL server in Guile.
00:09:05.720 --> 00:09:11.339
I called it `guile-ares-rs`, and used it
00:09:11.340 --> 00:09:13.959
with a generic nREPL client for Emacs.
00:09:13.960 --> 00:09:14.719
It worked.
00:09:14.720 --> 00:09:18.639
It had some rough edges, but overall it was okay.
00:09:18.640 --> 00:09:21.639
And after that, to add more features
00:09:21.640 --> 00:09:25.079
to make the implementation more complete,
00:09:25.080 --> 00:09:33.219
I wrote my own nREPL client for Emacs and called it `arei`.
00:09:33.220 --> 00:09:40.179
And I got almost complete Guile IDE in two months.
00:09:40.180 --> 00:09:45.319
So `ares-rs` is nREPL server implementation.
00:09:45.320 --> 00:09:49.679
`arei` is Emacs client, which uses the same nREPL protocol.
00:09:49.680 --> 00:09:54.439
It utilizes `sesman` package for managing sessions,
00:09:54.440 --> 00:10:00.079
the association of buffers with nREPL connection.
00:10:00.080 --> 00:10:04.379
It has some roots.
00:10:04.380 --> 00:10:06.639
The implementation has some roots
00:10:06.640 --> 00:10:09.979
in Geiser, CIDER, Monroe, and Rail.
00:10:09.980 --> 00:10:15.279
I took small snippets for some parts of functionality.
00:10:15.280 --> 00:10:19.479
I used the CAPF and xref infrastructure
00:10:19.480 --> 00:10:23.079
for completion at point and cross-reference capabilities.
00:10:23.080 --> 00:10:27.679
And by the time of conference, I hope
00:10:27.680 --> 00:10:30.199
that README will be complete enough
00:10:30.200 --> 00:10:34.179
so you will be able to try it yourself.
NOTE Demo
00:10:34.180 --> 00:10:42.679
Let's see what is possible with it already.
00:10:42.680 --> 00:10:46.719
Let's connect to nREPL server.
00:10:51.900 --> 00:10:56.280
After that, you can evaluate the expression.
00:10:56.281 --> 00:11:02.319
And you see the stdout and the result.
00:11:02.320 --> 00:11:04.719
Very nice, very convenient.
00:11:04.720 --> 00:11:08.659
You have different expression, you evaluate it,
00:11:08.660 --> 00:11:10.359
you get the value of the evaluation.
00:11:10.360 --> 00:11:12.279
You can run an infinite loop
00:11:12.280 --> 00:11:15.639
which prints to stderr and stdout
00:11:15.640 --> 00:11:18.599
and you see all necessary stuff.
00:11:18.600 --> 00:11:19.299
Very cool.
00:11:19.300 --> 00:11:21.959
But also, you can interrupt the evaluation,
00:11:21.960 --> 00:11:25.159
which is very convenient if you accidentally
00:11:25.160 --> 00:11:27.639
run an infinite loop.
NOTE Continuations
00:11:27.640 --> 00:11:32.939
Also, do you remember here we have a few more examples
00:11:32.940 --> 00:11:34.079
that we didn't try yet?
00:11:34.080 --> 00:11:39.159
For example, on usual REPL implementation,
00:11:39.160 --> 00:11:47.599
if I evaluate this expression, I get return value.
00:11:47.600 --> 00:11:50.759
I make a continuation and save it to this variable
00:11:50.760 --> 00:11:52.859
and I try to call this evaluation
00:11:52.860 --> 00:11:55.339
and I get an exception,
00:11:55.340 --> 00:11:58.399
because the environment in which this continuation
00:11:58.400 --> 00:12:03.479
was created was different and it has redefined
00:12:03.480 --> 00:12:06.159
stdout and stderr to capture it.
00:12:06.160 --> 00:12:08.979
But when I run it one more time,
00:12:08.980 --> 00:12:12.199
when I resume the continuation,
00:12:12.200 --> 00:12:15.799
the environment changed and it doesn't work.
00:12:15.800 --> 00:12:17.419
What happens in `arei`?
00:12:17.420 --> 00:12:21.759
I define continuation, I save the continuation
00:12:21.760 --> 00:12:23.479
for the simple expression
00:12:23.480 --> 00:12:27.279
and I resume the continuation with a new argument,
00:12:27.280 --> 00:12:30.139
and you can see at the top of the screen
00:12:30.140 --> 00:12:32.459
that it works perfectly fine.
NOTE Reading from stdin
00:12:32.460 --> 00:12:35.559
Also, with a usual REPL implementation,
00:12:35.560 --> 00:12:40.319
let's see what happens when we have a process
00:12:40.320 --> 00:12:41.919
which reads from stdin.
00:12:41.920 --> 00:12:48.099
I evaluate the expression and nothing visible happens.
00:12:48.100 --> 00:12:52.999
I can try to type `C-g`, `C-c`,
00:12:53.000 --> 00:12:56.559
and after some time it will say user interrupt.
00:12:56.560 --> 00:13:00.439
What actually I expect in such a case
00:13:00.440 --> 00:13:04.679
to have a minibuffer which prompts me for the input.
00:13:04.680 --> 00:13:10.019
When I evaluate the same expression in the `arei`,
00:13:10.020 --> 00:13:12.199
you see the prompt at the minibuffer
00:13:12.200 --> 00:13:21.899
and here I can tell, "Hello I'm a message from minibuffer".
00:13:21.900 --> 00:13:26.099
Cool. You will see that this message is printed to stdout,
00:13:26.100 --> 00:13:28.679
and unspecified was returned
00:13:28.680 --> 00:13:33.419
as a result of this expression.
NOTE Fancy example with continuations
00:13:33.420 --> 00:13:37.319
Let's make some fancy example with continuations.
00:13:37.320 --> 00:13:45.079
Continuations is a very cool mechanism
00:13:45.080 --> 00:13:47.999
which is not the topic of today's talk,
00:13:48.000 --> 00:13:50.999
but you can find a lot of interesting information
00:13:51.000 --> 00:13:54.439
in Scheme documentation or in related books,
00:13:54.440 --> 00:13:58.339
and I advise you to do it because it's really nice thing
00:13:58.340 --> 00:14:00.119
that is actually applicable
00:14:00.120 --> 00:14:03.519
in many different programming languages.
00:14:03.520 --> 00:14:05.199
Here you can see the infinite loop
00:14:05.200 --> 00:14:09.159
which just prints values increasing one by one.
00:14:09.160 --> 00:14:13.299
And here we save a continuation on each iteration.
00:14:13.300 --> 00:14:18.059
I can call the continuation
00:14:18.060 --> 00:14:21.939
and it will resume from the previous saved step.
00:14:21.940 --> 00:14:27.679
And you can see, it resumed from the same step
00:14:27.680 --> 00:14:31.640
we interrupted earlier, but we provided a new value for it.
another value for it.
00:14:31.641 --> 00:14:33.920
We can provide another value
00:14:33.921 --> 00:14:39.199
and it resumed from the same spot it was saved earlier.
00:14:39.200 --> 00:14:42.579
But I also can provide a `read-i` value
00:14:42.580 --> 00:14:45.199
and if I provide `read-i` value,
00:14:45.200 --> 00:14:50.779
the infinite loop will read the input from stdin
00:14:50.780 --> 00:14:53.319
and will continue the evaluation
00:14:53.320 --> 00:14:56.679
with a different `i` provided in this input.
00:14:56.680 --> 00:15:03.039
So let's try to type some arbitrary value
00:15:03.040 --> 00:15:07.519
and you see that the loop continued with this value.
00:15:07.520 --> 00:15:08.039
Very nice.
00:15:08.040 --> 00:15:13.159
And every time we could easily interrupt it.
NOTE Guix API
00:15:13.160 --> 00:15:17.319
Okay, what most annoying thing that I had previously
00:15:17.320 --> 00:15:19.339
with the usual REPL implementation
00:15:19.340 --> 00:15:22.759
that I have a quite nice Guix API
00:15:22.760 --> 00:15:27.579
where I can build packages, systems and other stuff.
00:15:27.580 --> 00:15:35.359
But if I evaluate this expression, I will get an error.
00:15:35.360 --> 00:15:38.039
Okay. I will get an error
00:15:38.040 --> 00:15:44.479
because I don't have an appropriate environment.
00:15:44.480 --> 00:15:51.579
But what I can do, I can connect to the remote REPL
00:15:51.580 --> 00:15:55.059
by creating a server with `guix repl --listen` command
00:15:55.060 --> 00:15:58.619
and connecting to it with `geiser-connect` command.
00:15:58.620 --> 00:16:01.819
And now I can evaluate this expression.
00:16:01.820 --> 00:16:03.359
Right?
00:16:03.360 --> 00:16:10.479
Wow.
00:16:10.480 --> 00:16:14.339
Okay.
00:16:14.340 --> 00:16:19.039
It actually doesn't matter for my example.
00:16:19.040 --> 00:16:22.879
I will explain how it doesn't work easily.
00:16:22.880 --> 00:16:26.519
This is a long-running process which prints something
00:16:26.520 --> 00:16:29.579
and it can take up to a few minutes.
00:16:29.580 --> 00:16:33.359
And for the whole few minutes I don't see any results,
00:16:33.360 --> 00:16:38.719
the same as with this infinite loop which prints to stdout
00:16:38.720 --> 00:16:42.199
but I don't see anything interactively.
00:16:42.200 --> 00:16:45.619
With `arei`, I can run
00:16:45.620 --> 00:16:47.920
the evaluation of the same expression,
00:16:51.440 --> 00:16:54.119
and you will see instantly
00:16:54.120 --> 00:17:00.200
that stdout is presented here in slightly yellowish color.
00:17:00.201 --> 00:17:02.920
I can interrupt the evaluation
00:17:02.921 --> 00:17:06.039
if I don't want to wait until it's finished,
00:17:06.040 --> 00:17:15.779
and just after that, I can evaluate another value.
00:17:15.780 --> 00:17:23.359
So that's cool.
00:17:23.360 --> 00:17:25.959
And let's see one more thing.
00:17:25.960 --> 00:17:30.339
We have an infinite loop and we have some completion here.
00:17:30.340 --> 00:17:32.579
And completion still works,
00:17:32.580 --> 00:17:33.659
very nice,
00:17:33.660 --> 00:17:40.259
while the infinite loop is running.
00:17:40.260 --> 00:17:42.059
Okay.
NOTE Support
00:17:42.060 --> 00:17:44.919
Actually it took me around two months
00:17:44.920 --> 00:17:48.039
of full-time work funded by my own savings,
00:17:48.040 --> 00:17:51.599
and you can support and help to the project
00:17:51.600 --> 00:17:57.019
using OpenCollective or by contributing on SourceHut.
NOTE Future steps - Multiple simultaneous evaluations in different contexts
00:17:57.020 --> 00:17:58.699
The future steps for the project
00:17:58.700 --> 00:18:03.674
include an experimental workflow where you have
00:18:03.675 --> 00:18:07.539
multiple simultaneous evaluation in different contexts.
00:18:07.540 --> 00:18:11.959
For example, you have Fibers, you have Goblins,
00:18:11.960 --> 00:18:16.919
you have some HTTP server or some other thing,
00:18:16.920 --> 00:18:22.119
and you want to run all of them independently
00:18:22.120 --> 00:18:25.319
in slightly isolated sessions,
00:18:25.320 --> 00:18:29.799
and you want to have the ability
00:18:29.800 --> 00:18:30.959
to still interact with them.
00:18:30.960 --> 00:18:33.979
For example, if they require standard input
00:18:33.980 --> 00:18:39.239
or something else, you want to be able to provide it.
00:18:39.240 --> 00:18:42.519
You want to see the stderr and stdout
00:18:42.520 --> 00:18:46.219
of those long-running processes and so on.
NOTE Tree-sitter integration
00:18:46.220 --> 00:18:50.239
The second thing is tree-sitter integration
00:18:50.240 --> 00:18:53.399
for better syntax highlighting, code navigation,
00:18:53.400 --> 00:18:56.879
and other features.
NOTE Full-fledged debugger
00:18:56.880 --> 00:19:01.399
And after that, probably we will do a full-fledged debugger
00:19:01.400 --> 00:19:06.239
so you can jump expressions one by one
00:19:06.240 --> 00:19:10.779
and see the results and see some intermediate values
00:19:10.780 --> 00:19:13.079
during the evaluation.
00:19:13.080 --> 00:19:14.479
And it's very possible
00:19:14.480 --> 00:19:17.079
because nREPL is a very extensible protocol
00:19:17.080 --> 00:19:18.199
and you can implement
00:19:18.200 --> 00:19:22.759
whatever you want on top of it.
NOTE FAQ - Does it support other Scheme implementations?
00:19:22.760 --> 00:19:27.079
I will answer two probably very frequent questions.
00:19:27.080 --> 00:19:30.499
Does it support other Scheme implementations?
00:19:30.500 --> 00:19:32.279
At the moment, it doesn't,
00:19:32.280 --> 00:19:36.519
but the Scheme implementation is not restricted.
00:19:36.520 --> 00:19:40.639
You have a server which is implemented in your language
00:19:40.640 --> 00:19:43.974
and you have a client--in our case, `arei`--
00:19:43.975 --> 00:19:48.319
which communicates with this protocol.
00:19:48.320 --> 00:19:52.359
So if you implement nREPL server in a different language,
00:19:52.360 --> 00:19:58.379
it should work with already implemented `arei` client.
NOTE Is it possible to use it with other text editors?
00:19:58.380 --> 00:20:04.079
And is it possible to use the same functionality
00:20:04.080 --> 00:20:06.999
in other text editors, for example in VS Code,
00:20:07.000 --> 00:20:08.679
Vim, whatever?
00:20:08.680 --> 00:20:13.799
Yes, it's possible and the case is similar here.
00:20:13.800 --> 00:20:16.599
You have already implemented nREPL server
00:20:16.600 --> 00:20:19.359
and you can write your own nREPL client
00:20:19.360 --> 00:20:22.120
in a different text editor and it will work.
NOTE Conclusion
00:20:22.121 --> 00:20:26.759
I would like to thank the authors and maintainers
00:20:26.760 --> 00:20:30.439
and contributors of Guile, Geiser, CIDER, Clojure,
00:20:30.440 --> 00:20:33.359
and Emacs, and all other people
00:20:33.360 --> 00:20:38.779
who are somehow related to the work on those projects
00:20:38.780 --> 00:20:42.079
involved in this talk.
00:20:42.080 --> 00:20:45.879
And I hope the Scheme programming will be enjoyable.
NOTE Contacts
00:20:45.880 --> 00:20:47.239
If you want to contact me,
00:20:47.240 --> 00:20:49.799
join #tropin IRC channel at libera.chat,
00:20:49.800 --> 00:20:53.039
or drop me a message via email or feediverse
00:20:53.040 --> 00:20:55.879
using `andrew@trop.in` handle.
00:20:55.880 --> 00:21:00.680
I will see you in a bit in Q&A session.