WEBVTT 00:00.000 --> 00:17.200 Hello and welcome everyone and it was done in 2026. Today we talk about Gile and tooling and 00:17.200 --> 00:25.240 some development practices. So this talk is targeted against newcomers who want to start 00:25.240 --> 00:32.640 with Gile or already experienced people who want to have more fun with Gile. And the goal 00:32.640 --> 00:38.120 is to get in as much fun as possible from programming in Gile language and for this we will 00:38.120 --> 00:45.560 be discussing the different practices and also we will be using some tools which have 00:45.560 --> 00:52.080 to properties. They are reliable and they are interactive and talking about interactive 00:52.080 --> 00:57.200 you not only can interact with them but they also fast. There is some research talking 00:57.200 --> 01:04.080 about the tools that when you interact with something with some program and it replies 01:04.080 --> 01:10.400 under 100 milliseconds it feels like instant response and you feel like engaged. If it takes 01:10.400 --> 01:17.120 a bit more time it feels slagger. If it takes more than one second you already distracted by 01:17.120 --> 01:24.080 but still can keep focus. And above the 10 second you switch into your context and you lost 01:24.080 --> 01:30.560 forever. So we try to be in the first category and 100 milliseconds and sometimes going a bit 01:30.560 --> 01:38.240 above. It's not completely covers all the edge cases and stuff but it will cover 80% of the 01:38.240 --> 01:46.720 goodness that you need to feel comfortable with Gile. The topics for today we will talk about 01:46.720 --> 01:54.240 triple. Most probably famous thing about this is a triple so cool tool for like interactive 01:54.240 --> 02:00.240 development of the stuff and a triple driven development of course. After that we will talk 02:00.240 --> 02:05.120 about organizational stuff, how to structure your code, how to structure your models, 02:05.120 --> 02:12.080 directories and those etc. A bit boring but important part. After that setting up the environment 02:12.160 --> 02:17.840 probably some of you hear a word geeks and I will mention it a few times during the talk. 02:19.120 --> 02:25.440 The next step will be talking about Enriple and what is difference with Reple and why it's 02:25.440 --> 02:33.360 important. A bit of topic of the next talk going beyond Emacs we will touch it lightly and I hope 02:33.360 --> 02:41.120 the next talk will cover it much more deeply and highly interactive development environments 02:41.680 --> 02:47.520 and development workflows and of course demos. How to debug Gile programs and testing 02:47.520 --> 02:54.560 and test driven development. So this is a sneak peek into what will be in the topic and something 02:54.560 --> 02:59.680 about myself. Probably already know me but for people who will be watching the recording, 02:59.680 --> 03:04.000 I am Enriple Trapin, I work on operating systems and programming languages and a lot of free 03:04.000 --> 03:09.120 independent sources of the way including those projects. Geeks home is a staff for managing 03:09.120 --> 03:17.440 your dot files and home environments and three will be using inside our talk for Dema and RG is 03:17.440 --> 03:24.000 going to Linux distribution based on GNU Geeks package manager and we also will use it for Dema. 03:24.720 --> 03:30.160 Suitable testing collaborate is a library for Gile for writing tests and executing Zemony Reple 03:30.160 --> 03:38.560 and in other way and RASGile ID. The primary thing that I personally use for development and 03:38.560 --> 03:47.040 hope after the talk you will use to. Usually when you start programming analysis you can 03:47.040 --> 03:53.600 see that Reple is the only thing that you need. The overall idea, by the way, who is familiar with Reples? 03:56.000 --> 04:02.320 Okay, I won't be explaining into my details so just long-running process that you like 04:02.320 --> 04:08.560 and incrementally modified by sending S expressions to the prompt and immediately getting the response 04:09.600 --> 04:16.000 like the value of the evaluation of the S expression. So it has immediate feedback and it's fun. 04:16.960 --> 04:23.680 I would like to show the Dema but probably all of you so how Reples works so I will skip this part 04:23.680 --> 04:31.120 and we will go to the next part. The Reple questions. When you start on a very simple experimentation 04:31.200 --> 04:36.800 or of course evaluating simple expressions and getting values is fun comfortable fast and all that stuff 04:36.800 --> 04:42.880 but when you build a bigger project it's a bit hard to manipulate on the smallest expressions. 04:42.880 --> 04:50.080 You need files, models, all that structure and you need to switch between your source code and 04:50.080 --> 04:58.080 Reple copies snippets back and forth. Then you need to, for example, get the knowledge 04:58.080 --> 05:03.200 where the function that you using is Reple is defined in your project or in your dependency. 05:03.200 --> 05:08.080 You probably need to construct another expression which will extract this information from runtime, 05:08.080 --> 05:14.640 not very fun anymore. Like to find function definitions to persist results, 05:14.640 --> 05:19.920 got to be a step back and forth, takes a bit of time. We can do better and I will show you 05:19.920 --> 05:26.080 in a few minutes how to do so and managing the library's dependencies and all that stuff. 05:26.080 --> 05:30.560 It's outside of the Reple scope and we will cover it soon as well. 05:32.240 --> 05:39.440 So Reple, quick and easy, not highly but interactive and it's a bit hard to integrate it into 05:39.440 --> 05:46.080 your text editor because like, of this back and forth jumping and even if you try to wrap it 05:46.080 --> 05:52.480 with some APIs, interacting with as to the in-reple, the single synchronous process is a bit 05:52.480 --> 05:58.160 tough and you can see the examples where it fails but won't be diving too much into it. 05:58.160 --> 06:06.560 But when the next time you will be programming in-gile, try to run something, for example, 06:07.840 --> 06:14.400 for evaluation and get some go-to-definition functionality working. If you use a usual 06:14.480 --> 06:21.360 as to the in-reple, it probably will fail. A bit of organizational part. 06:27.360 --> 06:32.960 If you have written in any language, which have models, it's often the case that models 06:32.960 --> 06:40.160 corresponds to the file structure and usually you name the models the following way. 06:40.960 --> 06:46.000 The project, your project name, whatever, you're the main or something like 06:46.000 --> 06:51.200 distinguishing the model from all as the models that possibly exist in the universe. 06:51.760 --> 06:59.600 The category and purpose or some other categorization approach and it corresponds to the file. 06:59.600 --> 07:05.600 It will be important a bit later but for people who come in it's better to know that 07:05.760 --> 07:12.160 it's good to keep these correspondence. The model and file hierarchy. 07:13.440 --> 07:20.400 Also, when you write in-gile, it's quite old language and people used it as a basket, 07:20.400 --> 07:27.680 so you have imperative code and you just load it into repel or whatever and it executes 07:27.680 --> 07:33.360 this code line by line. In modern projects when you have multiple models and you have such a file 07:33.440 --> 07:39.680 which have imperative side effect book code, when it will be loaded by the compiler or interpreter, 07:40.560 --> 07:47.120 it will fire those side effects and this is what we don't want when we have to be 07:47.120 --> 07:53.920 project the random side effects happening on the loading of the models. That is why every time 07:53.920 --> 08:00.800 when you define a model, to make only top level definitions of the functions, no side effect 08:00.800 --> 08:08.720 full top level code. What I mean? For example, if you write to the file, if you have something 08:08.720 --> 08:14.080 that writes to the file, it should be wrapped into the function. So before fighting the side effect, 08:14.080 --> 08:18.240 you need to call this function. You can call it from CLI, from Ripple, from whatever, 08:18.240 --> 08:24.800 but try not to use top level side effect full forms in your code. It will save you a lot of time 08:25.760 --> 08:31.920 and it will be much fun to work with. And the last thing that I recommend to make a 08:31.920 --> 08:38.960 correspondence between your usual models and models with tests, just by adding a test prefix 08:38.960 --> 08:48.960 at the end. And that's basically it about basic organizational structure after that. You have your source 08:48.960 --> 08:53.680 code, some way in the directory and you structure the models well, and you put your code well. 08:54.720 --> 09:01.920 Now you have another level of directory, that grows the code by pullpows. For example, 09:01.920 --> 09:08.960 your application wraps some secret. So it's better to create folder with C headers and 09:08.960 --> 09:15.680 wrappers and your folder with schema source code, which uses those wrappers. 09:16.560 --> 09:21.280 Or you have a back end part and front end part, or you have like something complimented in 09:21.280 --> 09:26.320 gileskim and something implemented in gileskud. It's better to keep in different directories. 09:27.440 --> 09:35.680 So later you can, for example, using load pass variable, specify where to look for the 09:35.680 --> 09:43.600 related source code for a particular part of your project. And we will see the example of this 09:43.680 --> 09:50.640 structure just in a bit. It's still a boring part, and I hope you get bored enough because 09:50.640 --> 09:56.800 like later we will have a bit more fun, but it's necessary to talk because it takes a lot of 09:56.800 --> 10:01.600 time from people who starting to work with them. And the last recommendations that I have 10:02.320 --> 10:08.800 to use a few top level directories. First one is ENV for storing all the information, 10:08.800 --> 10:15.520 scripts, and source code related to the environment, to how to set up the environment. 10:15.520 --> 10:22.960 Source code is a primary directorie way. You store your project sources. Test is a separate 10:22.960 --> 10:28.800 directorie from primary sources, because for example, when you want to release a project, 10:28.800 --> 10:37.120 you would like to be sure that nothing from your tests leaks into your release. Because you 10:37.120 --> 10:43.200 had like some draft or some incomplete functions or maybe some dirty implementations and helpers, 10:43.200 --> 10:48.640 you want to be sure that nothing in the release. That's why we separate them in completely 10:48.640 --> 10:54.240 different directorie. And DEF is a directorie for experiments, drafts, and all that seems. 10:55.120 --> 11:01.440 Okay, let's see how it can work. I will do a less. 11:01.520 --> 11:13.520 Okay. So this is a top level of some project, and you can see those directories I mentioned. 11:13.520 --> 11:21.760 And now let's see how the three looks like. You can see this a DEF directorie. Inside the DEF 11:21.760 --> 11:27.600 directorie, I have a directorie which says Gail. That means it's only a Gail source code. 11:27.600 --> 11:33.760 If I had a hood source code or C source code, it will be like a separate directorie nearby. 11:34.480 --> 11:41.360 And here you can see a lot of experienced mutations that I had, some demo files, and all other stuff. 11:42.400 --> 11:48.960 The end directorie contains quite involved structure, and I will explain it in a minute. 11:49.520 --> 11:53.360 But it contains information of how to set up the environment with geeks. 11:54.320 --> 12:01.840 And the primary source code for my project, which structures, as I mentioned before, 12:01.840 --> 12:07.680 a name of the project like category and purpose or whatever, particularization where you use. 12:10.000 --> 12:17.360 And tests. You can see the test like mimics the structure of the primary source code. 12:17.360 --> 12:24.800 But in the model names, I have a minus test for perfect extent, which helps if you keep this 12:24.800 --> 12:29.680 convention, which helps to do functions like jumping to the corresponding model with tests. 12:30.640 --> 12:36.000 And loading tests for the current model and all that stuff. Just a simple convention, but 12:36.000 --> 12:45.120 simplifies a lot of things. Okay. Now the load pass, who knows what load passes? 12:47.440 --> 12:54.880 Okay. Half of the people, very good. This is basically a place where your compiler looks up for the 12:54.880 --> 13:04.640 code. And one of the tasks that you need to do to work on a guide project or many other languages, 13:04.640 --> 13:10.560 as well, is to set up load pass correctly. So it can find your source code. It can find dependencies 13:10.560 --> 13:16.240 of your source code like libraries, compilers, and all that things that you will use. 13:17.040 --> 13:24.560 And I have quite extensive article. You can look it up later, but what else load passes allows us to do? 13:30.240 --> 13:36.880 It allows us to create a profiles, profiles for different needs. Sometimes we run and compile 13:36.880 --> 13:44.160 our source code for a list propose. Sometimes we want to run tests on CI. So we need not only our 13:44.160 --> 13:51.040 source code, but also our tests to be available for the compiler. And sometimes we need for 13:51.040 --> 13:56.880 development propose. So we need our tests, we need additional drafts, we need maybe some additional 13:56.880 --> 14:04.080 dependencies, which allows spying on our code and doing some debugging. So this mechanism 14:04.080 --> 14:13.520 allows us to create a profiles for different tasks at hand. And how basically do it in my project? 14:16.080 --> 14:24.960 I will show you right here. We have make files. And inside this make files, you can see that 14:24.960 --> 14:33.680 I specify different load passes for different proposals. For example, for dev, guide process, 14:33.680 --> 14:41.200 I use my source code, primary source code tests, and my dev with draft. But for running tests, 14:41.200 --> 14:47.520 I don't need those drafts. So I have on the test here. And for the list, I use only my primary source code. 14:48.400 --> 14:55.760 And I'm sure that nothing from my dev experiments and tests will leak into the final 14:55.760 --> 15:03.120 list, which is quite, quite handy. Okay, the question. You probably remember in the demos that 15:03.120 --> 15:11.920 I didn't show that I run the guide. And it spawns a ripple. And the question is where this guide 15:12.000 --> 15:23.520 comes from? The answer is where, no, which, which guide? The answer is simple from some strange 15:23.520 --> 15:30.800 place. Who installed it? How installed it? What version? What dependencies? Who knows? The only 15:32.560 --> 15:41.200 Richard Stoman maybe, not sure. It's better to control your environment. And all the dependencies 15:41.280 --> 15:55.040 that you have for a project. So we need a tool for this. It's not sponsored by Geeks, but unfortunately, 15:55.040 --> 16:02.160 unfortunately, unfortunately, I don't know a better option so far to do so, so we need to use Geeks. 16:02.160 --> 16:12.640 There's one important thing to note that installing Geeks and doing initial Geeks pool can be 16:12.640 --> 16:19.200 a bit slow. And like, I like it some time in advance if you want to use Geeks for managing 16:19.200 --> 16:26.160 your guide project. But when you set it up, it's extremely reliable. I have projects that, like, 16:26.240 --> 16:32.640 a few years old, I come back to them and they work perfectly without any issues because they're 16:32.640 --> 16:43.200 frozen in time with Geeks and it capability for time traveling. Oops, let's go to the next slide. 16:43.200 --> 16:54.000 A bit of good best practices. Good best practices. So how basically 16:54.960 --> 17:02.000 things works? Probably I should start from this slide. We installed Geeks somehow. Imagine, 17:02.000 --> 17:08.080 imagine, we could do so. After that, we need to use two things. The Geeks shell and Geeks time machine. 17:09.360 --> 17:17.520 Geeks shell allow us to install a guide. And for example, a guide, a QR code. It's sponsored 17:17.520 --> 17:23.600 shell. You can see that prompt is a different right now. And it has additional character in it. 17:23.600 --> 17:30.000 And if I run a guide variable and inside this guide variable, we'll do use models QR code. 17:32.800 --> 17:41.040 It will work. But if I run a guide outside of this shell and we'll do the same thing, use models 17:41.840 --> 17:48.960 QR code. It will fail. No code for model and QR code. So now we can create a shell 17:48.960 --> 17:55.520 and the environment where the guide and the dependencies are available and they have some version. 17:55.520 --> 18:03.360 Which versions they have? I don't know because the Geeks comes from some random place and it has 18:03.360 --> 18:11.040 a random version. And the packages it installs will be of random version. So to be sure that we 18:11.040 --> 18:20.080 use exact versions of a guide and libraries, we will do another trick. We will use Geeks time machine 18:20.080 --> 18:29.760 and specify this long pass to channel system file. I will show what inside it. And we create the same 18:29.760 --> 18:40.000 shell and voila nothing works. Geeks time machine, minus C blah blah blah, minus minus shell, 18:40.960 --> 19:01.680 shell, and we have another shell. But right now I know exactly which version of 19:02.000 --> 19:08.720 use and which version of guide QR code I use. That's because we used time machine and specified 19:08.720 --> 19:20.240 channels SM where I have an exact commit of Geeks I use. So what we did? We pinned it down. We used 19:20.240 --> 19:26.800 exact version of Geeks. We instantiate that exact version of Geeks and after that we created the 19:26.800 --> 19:33.920 environment. So treat this process as two step process. We have some Geeks from some Geeks we create 19:33.920 --> 19:39.120 an exact version of Geeks and this exact version of Geeks create the exact environment which will 19:39.120 --> 19:46.480 be reproducible across different installations, people and servers or whatever. And another recommendation 19:47.280 --> 19:56.640 treat Geeks as a guide library and make it respect long passes. You will use it if you do any 19:57.120 --> 20:00.800 Geeks related stuff like managing your channels, configurations, and whatever. 20:04.000 --> 20:12.800 Okay, that was fast. Okay, very quick to the demo. The Enreple stuff. 20:13.520 --> 20:19.360 Enreple is not a rebel. It's a protocol which allows to communicate with the guide process. I synchronously 20:19.360 --> 20:25.760 and do a lot of integrations and cool goodies. Unfortunately, that I didn't watch at the time. 20:26.400 --> 20:38.320 But let's do some demo. I have a lot of them and they are fun. But we will do something very simple. 20:38.400 --> 20:56.880 You know, this is Emacs and we can spawn a Gile Enreple server connected from Emacs 20:56.880 --> 21:04.480 we did it just like this and start the video in random expressions. You see, we will let this play 21:05.120 --> 21:10.080 it printed high to us to the out and the return and specified value. They have different colors, 21:10.080 --> 21:18.320 so you can distinguish it. If we have a few multiple values return, you will see, you will see them here. 21:19.120 --> 21:27.600 Now, for example, you know that you have a call with escape continuation function and you see there's 21:27.760 --> 21:38.240 no completion for it. We need to export some model or import. I don't remember which way we go. 21:39.040 --> 21:48.480 And now you see escape continuation, completion appeared. Cool. Now let's run infinite loop. 21:49.040 --> 21:56.320 And while this infinite loop running, we want our completion to work again and it still works. 21:56.320 --> 22:02.880 Very cool. In some other places it won't work. And we execute the infinite loop, 22:02.880 --> 22:09.280 but actually we didn't want to continue with it as a stuff. Let's interrupt this infinite loop. 22:10.880 --> 22:18.640 So good, so far. Anybody hear about continuations? Cool. It's very, very tricky 22:18.640 --> 22:27.040 computer science stuff, but what it allows to do. Like inside this infinite loop, 22:27.040 --> 22:33.200 in an infinite loop, I save a current continuation and this is things that I can resume from 22:34.400 --> 22:42.400 interrupting our infinite loop. And you see there's a call to quant, quant is a saved 22:42.480 --> 22:48.320 continuation. We can evaluate, oops, the value you see is a continuation is a return. 22:48.320 --> 22:56.560 And we can run this continuation again. And if you didn't notice, it continued this infinite loop 22:56.560 --> 23:04.320 from the point it stopped before. You see, we was at this place and we started again from this place. 23:05.280 --> 23:13.520 What else? We can call the continuation again with a different value, which is a read number. 23:13.520 --> 23:21.120 And at the bottom of the screen you see a prompt. It asks for the value from SDN. And I can input 23:21.120 --> 23:28.080 some number into it. And you see, it continued this infinite loop, but started with much larger number. 23:28.960 --> 23:34.480 And now, we will go to the next demo. Next demo is related to stack trace. So one of the big 23:34.480 --> 23:42.960 pains in guide development is debugging. And when you get exception, it's hard to understand 23:42.960 --> 23:48.960 where the things went wrong. The reasons I explained in the article actually useful 23:49.040 --> 23:54.640 stack traces that you can find in the internet. But let's imagine that instead of the number we 23:57.680 --> 24:03.920 gave a string or something invalid. And you can see that I got an exception and stack trace 24:03.920 --> 24:12.640 on the right. And I can jump around and I immediately jumped to the place where it failed. And it says 24:12.640 --> 24:20.800 that I is false instead of some number. So somewhere here in string to number 24:22.400 --> 24:29.920 converted our value from readline into false. This probably because we used a string instead of 24:30.800 --> 24:36.320 a number. So we found out the problem and we can restart the loop and use number next time. 24:36.960 --> 24:43.680 But maybe it's not that impressive. The impressive thing happens when you have a huge project 24:43.680 --> 24:49.760 of, I don't know, thousands of the length. And this is my personal configuration which is connected 24:49.760 --> 24:58.320 to the nulline distribution. And this is a problem in it. Let's try to build it. 25:07.200 --> 25:14.640 And you see something that's not very helpful. From this error message, it hard to understand what 25:14.640 --> 25:24.560 is going on. But if we run areas and reports over, connect to it and try to evaluate the 25:24.560 --> 25:32.320 configuration, you will get a very obvious stack trace with which says, expecting pair, but got a string. 25:32.960 --> 25:42.560 A pair is actually a list in in scheme. So it's expected a list not a pair, but whatever. 25:42.560 --> 25:51.440 And you can jump through the stack trace and SSH key, question mark failed. And it failed inside 25:51.520 --> 26:01.680 feature a groupage. And here I see that SSH key is a list of one string, a string, but it should 26:01.680 --> 26:08.880 be a list of lists of string. And after that fixed, I can evaluate the model and it evaluated 26:09.920 --> 26:18.000 correctly. And I restart the rebuild of my home environment and it will work perfectly. And in 26:18.000 --> 26:26.560 another small thing that I will show you in a moment. This is IMAX. I know that not everyone 26:26.560 --> 26:36.720 uses it. And like it's understandable. The good thing that our ID consists of two parts, 26:36.720 --> 26:43.840 areas part, which is an variable server and array part, which is a client. And here like a few 26:44.240 --> 26:54.320 hours ago, Ilia the fellow hacker sent me a video. He opened his NLVM and used a generic and 26:54.320 --> 27:05.360 repell client and connected two areas back end. And he get all the goodies of ID inside his NLVM as well. 27:05.920 --> 27:15.040 So you can see, he can evaluate arbitrary expression and get immediate results. And it all 27:15.040 --> 27:23.840 works through the array that we implemented for our ID. Okay. And on this wonderful note, let me find 27:23.840 --> 27:32.000 my presentation. Oops, sorry. Here, I will jump to the end. I will say that I like teaching 27:32.080 --> 27:38.640 a lot of teaching computer science and building to tackle a hard problems. And those tools I mentioned 27:38.640 --> 27:43.840 today make it actually fun. And I hope it will make some fun for you. 27:43.840 --> 28:10.720 I think we have time for one question. One question, please. Only one. So cool, talks. No questions. 28:10.720 --> 28:34.320 Okay. I did. Yeah, okay. This is a step debugger in NLVM. We looked at it more over, 28:34.320 --> 28:43.360 we did some work during the internship this year with NLVM and Nicolas Graves. And made a proof 28:43.360 --> 28:53.680 of concept of debugger for areas. It works. It has like a relation in a point of failure where 28:53.680 --> 29:01.280 the exception happened. And we also had a very bare bond proof of concept of step debugger as well. 29:01.280 --> 29:07.440 It's in development, but maybe someday you will see it. Okay. Thank you very much.