Valigo’s macro is a brilliant display of Jai’s metaprogramming power that elegantly erases boilerplate while dangerously blurring the lines of explicit control flow. It perfectly illustrates the tension between developer ergonomics and the transparency required for systems-level debugging.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Valigo’s cursed jai macrosAdded:
If you If you like go down, like I think you have pointers, like pointing to memory. It's like ASCII art, like what happened, like >> And it goes on and on and on and on and on and on, right? I found a program that let me like explore macros interactively. You just like paste a macro code and it you know, and bind it step by step.
>> expand expand expand. [laughter] Like this language, it doesn't feel like something that shipped to you by corporation. It's It feels very personal. You have like a lot of like jokes and how-to and personal [music] touches.
Nuno Afonso who made RGCS in Jai. I think he's like former member of Jai beta.
Um He says, "You should ask Valigo to show his or return abominations."
programming Yeah, this is was like I just you know, I'm as a beta tester, I wanted to test the beta and I just went on a tangent of implementing the most like horrifying stuff by just like just see how far metaprogramming in Jai can go and it can go pretty damn far. So, I've implemented or return like in as a metaprogram in Jai, so you can wrap anything in or return and it would work exactly as you would expect and like even further. Like I I pushed it a little bit further than it does than it goes like in Odin. Uh so, I don't know if I can like showcase it running because it's probably not, but I can show the code. Yeah, I think we can walk walk through the code. The module is called like control flow. I have a couple, so I have a logging macro here that's that is actually usable. I I use it in my projects. But, here's also like or return.
Uh Choo choo choo choo choo choo choo choo choo choo Yeah, let's do it like this.
And so, there's a lot of stuff here. So, this is the implementation for it's 300 lines of code uh here and also there's like build a Jai that also has Can we see Can we see first the usage and then >> Yeah.
>> [clears throat] >> So, yeah yeah. Let Let me Let me go.
So, I think it's commented out.
So, let me uncomment this.
Uh there was like a usual one. So, this one is just some commented code. Yeah, I commented it to test logging. So, I guess we can we can look at this code.
Uh so, if you have a function and it like returns something. So, for example, it returns an int, string, and float. So, Jai has multiple returns kind of like in Golang. Uh exactly like in Odin.
Uh And so, you add something in a hash table. Right? And then you try to find something in the table by this key. And for example, if it's not found you return, you know, like some defaults you specified.
So, this is like the usual code. Like if error not equals nil, blah blah blah.
Same same thing here. If not found, return this.
But, what this macro does, this or return you can do exactly the same thing. Um whoops.
So, you just wrap table.find in or return and get back the value. And if the value is not found, you are returned from this function.
So, you don't see return here anywhere.
It just gets inserted here automatic.
So, in Odin it would be uh table.find right?
or return.
Uh and or return in Odin works in a way that if you have uh named returns, you need to I think predefine them beforehand or something something. There is like a restriction, which is made like for a good reason. But, for example, you just return, you know, like zero, string, and 0.0. So, this is how you would would write it in Odin. Oops, sorry.
Yeah. But, here This is not a valid valid valid syntax in Jai, but here you just wrap it in or return.
So, you >> the idea. You're saying that a nice return is already defined. So, this will be return 96.
But, for string and float Yes, so this would return 96.
Yeah. Uh s s the string the empty string and the 0.0.
Because those aren't defined.
So, we defined this as a named return inside of a function. So, it will actually find that okay, this is already defined in the body of over procedure.
Uh string and float are unnamed, so it will just return defaults for them.
In this way. And if I would for example say like, you know, return string, right? And I would define it here like right the default it would return this in case of a failure. Yeah.
Hi everyone. Let me take a break to thank members of the show who made this conversation possible. Members get earlier access to videos including longer unedited footage from live streams as well as they're invited to our private Discord server. If you want to support this show, there is no better way than becoming a member on YouTube or Patreon. [music] Thank you so much.
Yeah, from here. And you can you can see that what or or return does, right? Just a way to return from a function with some default values.
Yeah, and so what or return is. So, it's not a simple function.
Uh or return is actually a macro. And if you see the preview >> [laughter] >> it's actually a lot of them here.
Yeah, so the way it works, let's go to um to or return the file.
Can we do bigger? Can we do bigger? Uh yeah, let's do it let's do a bigger font. Let's maybe do 20 and uh 23. This is probably bigger, right?
Yeah. We can do even more. We can do more, yeah. If you If If you can, you can do more, yeah. Yeah, like this maybe this.
>> Nice nice No Oh, nice nice.
Yeah, okay. I Let's Let's do this. And so, or return, this is actually a string literal.
This is not an actual code and you see we have here uh this is like here string.
So, or return template, this is a template.
A template not as in C++, this is just string literal. I have syntax highlighting here. Right? But, uh only because like my Emacs knows that oh, it has a code tag, right? If I change it, it will like highlight everything. And so, yeah. This is like the real thing. It It's just a string.
And it has some kind of holes in it. So, for example, here.
Uh formatting something will be inserted here.
Uh something will be inserted here.
Something will be inserted here like this four. Yeah. And then Yeah, and and it has like some code. So, here's the end of the string template. So, this is the string template.
And uh what is happening with the string template? So, let's find the usage of the string template.
Uh there is a This is an actual code. Or return add source. So, what it does, it loops for 10 and it generates 10 variants of or return that returns up to a 10 outputs.
So, in Jai there is no So, for now in Jai there is no way to uh detect how many return values you need at compile time and then insert exactly as many or return uh like overloads as you want. So, you kind of okay, let's support up to like 10 returns maximum. And we'll like just insert 10 different or returns into the target source. And the way it works the way it's going to work is uh build added string, I think it's here. Yeah, so this is an actual inserted code. So, when you compile the thing, it will insert this or return that you see supports one return.
The one that supports two returns. The one that supports three returns and up to 10.
Uh again, this is kind of a hack because in Jai you can't determine this thing at compile time because the thing needs to get type checked.
So, if you call a procedure that doesn't exist or a procedure that has incorrect number of return, the Jai won't let you like a handle type check error. And this is one of the feature requests actually that I'm pretty sure John is aware of. Just let you handle a compile error in a way to fix compilation. So, for example if we had an ability to catch a type check, you know, oh or return that returns three arguments is not defined. And you can just insert it at compile time. Here, I can provide it to you. In this case, we would need to we would not need this hack.
Hope it makes sense because Jai already has this for imports. So, if you import a package that does not exist, you can provide it at compile time.
This is for example how uh so What? There's a guy his name is Yeah, there's a guy his name is Judah Caruso and he wrote a Lisp that compiles to Jai. And the way it works is that you import a Lisp file in Jai and at compile time Jai kind of fails to import the file and in import handling error, he would translate this Lisp into Jai and then provide it as an import.
>> [laughter] >> So, here you can do this. You can also just, you know, if you fail some to import something, you can at compile time curl over the internet, like download code from GitHub and import it.
So, I I guess something like this exists already in the language, so we just can't uh handle type errors like this.
Yeah. And so, what I do is I literally insert 10 different all returns into a source code till it compiles. So, that's I guess this is me avoiding limitations in Jai metaprogramming.
Uh after I do that, it's all golden. So, here is my actual metaprogram.
Uh so, here is uh let me scroll. Big font. Yeah. So, here's a part of my metaprogramming.
When you want to use all return, you just hook your uh type check handler in the compile time with this function. And what it does, at compile time, compiler kind of feeds you everything that got type checked.
And so, you can handle. So, it's called message type checked. It just tells you, "Okay, we type checked a procedure body.
We type checked procedure header. We type checked like a declaration." Stuff like that.
And you can parse it.
So, you say, "Okay, uh I get like expression. So, you know, I care only about procedure bodies, right? This is a way to tell Jai that if it's not procedure body, don't care."
So, if you type check procedure body, which I check if it's already been modified. In this case, we kind of nope out of it.
Uh but if not, we take a block of a procedure body.
We go through each statement in the procedure recursively, because it can have multiple scopes and stuff like that. And then for each subexpression, we kind of check, "Okay, is it a declaration?" If it's a declaration, uh where was it?
Header returns. What's that?
Oh, yeah. So, I kind of pre-save uh what our So, procedure body, it's usually attached to a procedure header. And from this procedure header, we can get what this procedure returns. So, we get all return like arguments and types. So, here are their header returns.
Then, when we get a declaration, we kind of see if declaration is declaring something that procedure returns. So, in our case, if you remember, uh mean the Jai, is this scenario. We have nice return that is equal to this. So, it handles this kind of scenario.
Yeah, we see that, "Okay, name is exactly the same as in return." So, I kind of just add it into array of declared name returns. And yeah, with the name.
If it's not a And then, I care only about procedure calls, right? So, I I look for call that is all return.
So, there it is. If it's a call, I get the call. If it's not all return, I nope out. Otherwise, here is the handler.
This is how I modify procedure body to insert all of the like return stuff.
And so, what we do, I create a identifier.
Uh I uh set identifier name to a name of my procedure. Then, I create a declaration with a So, this is just you write you create the Jai code kind of with Jai code. This is you know, But didn't you didn't you want to just enter uh add return statement, right? Like why do you not create identifier?
>> get we'll get to it a little bit uh later. So, what we need to do is um So, what do we need to do here? Let me remember. I haven't looked at this code in a while.
Identifier.
So, declaration.
Header resolved. Oh, oh, oh, oh. Yeah, yeah, yeah, yeah.
Uh So, it's It's going to be easier if I go back to the code. So, what we do here, since this is not I guess I should have mentioned it. So, this is not actually procedure call.
So, we don't call table find and then pass a result to all return. No. This is passed as a code.
So, this is the same as doing it like this.
Ah, it's a string. You need to call it and you need to save the result and need to see what happens.
>> this is passed inside as an AST. Okay.
Yeah, because if we go back to our added strings, all return, it accepts the code as its first argument. Okay. This is where we get into this Lisp analogy, right?
Because you can pass code as data. So, it looked like a procedure call, but it actually gets passed as an AST. And uh you could write it as a code here, so then it kind of reads better in the sense that you know exactly, right?
Okay, it's a code.
But I mean, if you know what all return does, you don't really need to do it all the time.
Uh so, this is why in this metaprogram, I need to parse this code. I need to get what exactly we are calling. And so, here, I construct a procedure call from that code that is passed in all return.
And so, when I do that, and I pass it all the arguments. So, what this code does, again, go back here, is it reconstructs this AST as a procedure call. So, it puts it like here.
Yeah.
Yeah.
Uh and it also assigns all the all the return values that it has.
So, this is what it does. And yeah, you can see like call arguments. And And then, when I modify that, when I turn it into a call, I modify procedure with the new body.
So, this is all it does.
And this is me just extracting this code out of all return and inserting as like a regular thing. Then, this is the first part. To actually call the procedure and assign everything that it's needed it's needed.
Uh after this happened, we need to actually handle all return part part Yeah, and what happens there is that all return itself has a modify directive.
So, what is a modify directive? You know how in Rust, uh you specify type boundaries or trade boundaries.
It's when you have a procedure of like function declaration, and then it has some sort of parameters, and then you you say like, "Okay, this one needs to have like traits maybe plus sync plus like copyable plus like traceable." And And you have like a where here, and where has all this like types like summed together like nested where's. And it's like a language within a language.
It's like a sublanguage that you need to learn. And TypeScript has exactly the same thing, where you also have where, and then you do like type type language.
>> And Java and C++ too, and etc. >> crazy. It's crazy because you need to learn two different languages to write one language. And it's so crazy that in TypeScript, this type expression is also Turing complete. Yes.
Yes, so [laughter] So, and in Jai, to to not have this craziness, you just write the language.
So, you just open modify procedure, and here you get all of these like So, you have every argument as a variable.
And okay, here's the code. It's input parameter.
I can operate on it and do everything that compile time support I can like open a file here.
So, yeah. But this is So, what I do Wait. Yeah. Wait. Because I I I like I thought I knew metaprogramming in Jai, at least as what can be done. But this is more because I know that we can com- call the functions at compile time with hash run, or we can also listen to the messages that are coming when you when you do the compilation.
>> But this, when is it being triggered?
Yeah, yeah, so uh it's it's getting triggered when the language does uh like a generic resolution, something like that. So, for example, if you have multiple variants of the same function that accepts a generic argument, uh you can either reject this overload. So, for example, So, for example, here, I check what kind of code you passed there, right? Compiler get nodes.
And if it's not a procedure call, because all return can only wrap function calls. Yes. And if you pass anything into that's not a function call, I just return false and say, "All return macro only support procedure calls." So, you get this as a compile time error.
>> Ah, nice. Yeah. And in Rust, you would say like, you know, where like code that kind like is a something like that. So, here, I can just write a procedural code that says, "Okay, if whatever you passed here is not a procedure call, get a compile error."
And it will get you compile error with the line, a column that will lead you to the place, so you instantly see like it it will show color code. Very nice.
After that, I parse this call here.
And whoa.
Sorry.
Yeah, so uh expression kind, procedure header.
Uh what's that?
Resolved.
Unexpected result procedure expression.
I don't know why header Ah, ah, ah, no, no, it's it's it's a different one.
Yeah, so code, we need a procedure call, procedure Ah, yeah, yeah, yeah, so Uh, I I guess not all procedure calls are procedure headers. So, I don't remember why I did that. Probably handles some like edge case.
Yeah. Uh Yeah. Anyway, then I parse the header.
I get all the return values, and then it checks how many return values are there.
And you can see it's like template, so each overload handles its own like amount of procedure headers. And if we go back to a concrete one, so for example, our return that works with three of them. So, here's how it works.
Uh, if return values less than four, right? Because it's like 4 - 1. One of them is like an actual uh So, how do I uh explain it better?
Um One of them is like a success or not.
So, it's like okay, the first one. And everything else is what you actually need. So, I check the amount of arguments. Otherwise, another compile error. Procedure should have exactly blah blah blah return values, but it has this many.
Yeah.
This is actually more of a guardrail because since we have overloads predefined, this will probably never like triggers.
Uh, then I declared output types here. So, this is just a default, and then yeah, I kind of match if these return arguments against whatever this has.
So, just okay, procedure that we wrap has three return arguments. Their types like int, string, float. So, I assign T1 like the return T1. This will be int, this will be string, this will be float.
So, I assign it here, and then return true, so we accept the overload. And this is how we uh match all the types because So, Jai is a compile-time language.
Type of everything needs to be resolved at compile time.
That's why this is kind of important.
And this is why you can just insert a string literal as a code because the compiler will parse it, will type check it, and only then it will insert it. So, even if you like do a like incoherent like string templating as it might have looked right, you will get this file added strings with the code fully composed, and when you debug it, your debugger will literally get dropped down here, so you know exactly what resulting code is. It's like This is actually immensely useful because you can debug meta programming at run time through these files. And this means that like meta programming is here to stay, meaning like in Jai it's now it's maintainable, you know?
Like if if somebody would wrote like a huge wild C macro heavy code and then left the company, you're like you're like you just want to get the rid of this code as soon as possible because you don't want to do anything with it.
Like you don't want to stand near this code. And here you have like, okay, just like let me debug this like Yeah, and I actually So, I don't before we continue, I don't write a lot of C code, but I read C code all the time.
And uh reading macros and debugging macros is really hard. So, I I recently been like I think at some point I just got so like tired, I found a program that let me like explore macros interactively. I just like paste a macro code, and it's you know, unbinds it step by step.
>> Expand. Expand.
>> I got so impressed by that, I even like recorded a video just to like shout out this tool.
But in Jai, yeah, you can literally just debug it. Here's like generated code like go wild, inspect it, put the breakpoint here. Yeah.
And so, after we did all Ooh.
Uh, after we did all that here's an actual body of our return. And it just calls our return inner.
Uh, it inserts So, insert scope, it means that we insert the code, whatever this generates, into a scope of the code that is provided here. In other words, so whatever our return is returns as a code will get uh inserted. So, here's our example. We'll insert it into the scope of this calling function.
And we'll operate on like this variable stuff like that.
Yeah, so yeah.
And uh our return inner Is it here?
No, it's Let me search where it's like defined.
Yeah, here it is.
And this actually a meat of our return itself.
Right? So, it kind of just again parses the procedure header, and it's a little bit of a duplication code because uh doing this does the same thing as modify does.
It doesn't need to do it strictly, but I was experimenting like where it's better to throw a compile errors, which generates like better error messages.
And uh I should just remove I should just delete this and leave modify because modify generates like better errors. So, this is just like a duplication code that shouldn't be here.
Uh, it does the same thing. It parses call code that you get. Can you say it again? Sorry. Can you say it again? Can you say it again? You should do what? Remove what? I I tried >> just remove this code. Yeah, this code is it's like literally not needed. It's it's copy-paste from modify. I was just experimenting like which way produces better compiler errors.
Okay.
>> Because we already we already pre-checked all of this in modify, right? And if something here is not right, we just reject the call.
>> Yes. Okay. Okay. Okay.
>> just duplication, yeah. Here's the meat.
Uh We parse the outer procedure. So, we parse This will be like foo.
So, our return gets called within foo, and this will be foo.
Uh, so in before that, we uh parsed like table find, the thing that we wrap.
And this one parses foo, so the thing that is uh that calls us. And we need to we need to do it to produce a correct return.
So, uh we have two set of returns. One is whatever table find returns.
So, whatever file table find returns, we will decide if we need to return out of outer function or not. And like I'm I'm sorry if this, you know, like ex- mind [clears throat] ex- This is something you get used to when you do a lot of meta programming. Or if you do Lisp, you're like, "Yeah, yeah, yeah, I understand. Like go on."
And if you don't do that, you have you have no idea what you're talking about.
Like this is this [clears throat] is weird at this point. Like I'm like I kind of know, but I need to, you know, like I would need the piece of paper. I'd be like, "Okay, this is this. This is that.
Here's a point that like here's like an arrow."
Yeah, it gets like a bit complicated because you write code that talks about the code, not about some like logic. And yeah, it it gets a little bit You need like to get used to it a little bit.
I guess functional programmers are are better at it because they constantly thinking like higher level, you know, everything. Higher level of functions, yeah. Yeah, this is a code monad. I Yeah, of of course, like, you know, like Drake meme.
>> [laughter] >> But yeah, so And And a good thing is that if something goes wrong, you can always like inspect types.
It's It's very inspectable. If something goes wrong, you can always like trace it step by step. So, you're the language in this case is very like it it it helps you a lot.
And what you do here is like you take returns. So, in our case it's going to be these returns.
So, first we checked returns from here from this one. Now, we check these ones.
And uh we prepare a string builder. And here you see percent equals percent. So, we build a code that uh prepares like an outer return. It literally so adds like entry name equals to C default type as a string.
So, if we have declared name return, so int was declared, we just insert it. So, it So, this thing will going to produce like return like, you know, what was it again?
A nice return, yeah.
Nice return.
So, this will this condition will produce that.
Otherwise, it will produce uh name equals default. So, uh if we have a name, yeah. If If you have a name that's not defined, otherwise, it just like you know, like this. Yeah. Or like 0.0.
So, this construct this if-else constructs a return string like this.
Uh, and adds it to a string builder. And default type as a string, this is actually a part that Odin doesn't do.
Uh, it says that if you have named returns, you need to like all define them or else. I think so. I get I guess again, if if it's not the case, like feel free to correct in the chat. And I just like, "Oh, what if we actually do it?" And I remember while implementing this, I actually realized that, "Oh, yeah. I I can see like this restriction." It's not like purely technical. It's actually because it just makes situation more confusing because oh, you defined one of them but you haven't defined others. And it just gets harder to kind of string it all together but for me it was like an exercise, you know, if I can.
And this is just literally I just check the type info or return. And oh, if it's string, here's like default string. If it's an integer, zero. Bull, false. Blah blah blah blah blah.
And if it's like an enum, I think this is irrelevant now because language recently uh Jai recently gained tagged enums.
So, this was me just like a kind of a guessing. Oh, no, no, sorry. It's a enum, not union.
>> Yeah, it got tagged unions, right?
Yeah, it got tagged. And I actually don't even Yeah, I don't even handle unions here. I guess I just forgot about their them existing. But yeah, like you can handle every type and provide some kind of a default.
And this is what we do here. I just construct the default returns. And after everything we have another string builder that you see it's like inserts a scope here like opening bracket. Then at some point it's going to be like closing bracket like here. And it just Yeah.
Pace a bunch of returns that it later returns as a code. So, because this inner, if we take a look here, it returns a string. And if you remember or return put like insert the string as a code. So, again it gets type checked and stuff like that. Maybe if we have like another edit string here, do we have?
Uh do we have a resulting code here or not?
Uh I don't think we do yet because I haven't like actually compiled it. But I hopefully at this Oh, yeah, yeah, yeah, yeah, yeah. Here it is.
So, yeah, this is what it does. So, this is the final code. Return one two table find. If not return one. Backtick return nice return this and this. So, backtick return inserts return into an outer scope.
Yeah, otherwise we return red two from the macro. So, this thing gets inserted in in this place. So, like kind of like this. So, instead of this we have like table find expands like that. And then it checks that return this backtick return means return out of this one. Otherwise, this return would be assigned to this value.
>> Can you Can you Can you zoom in on this difference? If you do backtick return here like return red two is still here.
So, Return red two is not here. It's inside of or return macro. So, the normal return uh yeah, so the normal return No, this is the wrong one.
Yes, so the normal return is it gets put like in one of these. So, the normal return returns from or return.
Uh so, this is like macros they're kind of like regular procedures. You can return value from them. So, your macro can return in. Uh okay, you return from macro and this is backtick return you want to insert return statement.
>> backtick return returns from an outer function. This is how macros are different from normal procedures. They let you mess with an outer code. Got it.
Yeah, so if the if like the condition is wrong, I return out of here. Otherwise, I just assign this value from from this one and proceed with the code. So, this is like this is how or return can be implemented in Jai as it currently stands.
>> Nice. By the way, nice. Impressive. I thought that like >> [clears throat] >> if I were to do it, I would just do like the first version, first draft. I wouldn't bother with all the types. I'd be like oh, it can return string. I'll name the returns. I don't want to bother. And you went like full on like handling the edge cases, dude. I'm like >> It was like two stream sessions each of which was like six hours long, something like that.
And yeah, it was just like okay, how can we do this, you know, like for real, you know, like for real?
And so, it was like oh, yes, like yeah, yeah, let me do it real quick. No, no, no. It was actually like hard.
It expanded my brain. And I had few like iterations of it. So, yeah, it was actually hard to do. And I even used it in one of my projects because I thought I'm going to need but at the end I I I'm not even using it because it's just like so niche and also I found that every time I want to return uh because something didn't work, I always almost always want to log it uh first. Okay.
>> Yeah. And uh so, I created another one that's >> [laughter] >> way easier.
It's called like with error. Yeah.
>> And it does similar similar stuff.
Uh yeah, so it it does similar kind of thing. But what it lets you do is Oh, let me actually go to main. I don't need to run it like through the code because it's it's much easier than on return.
But here what what does? It's just with error like read entire file, right?
And if it returns an error like an error code, right? There's like an error value, error string that gets inserted and you just can log it here.
So, that's So, this macro it just wraps whatever procedure call and whatever is here, if it returns an error, you can just log it. So, what this does, it it lets you to not like uh grab these from like OS module every time.
So, you know, in on Windows [clears throat] you would get like get last error. Yeah, yeah.
>> And you would get an error code. And then you would need like a string description of this error code. So, this macro kind of automates it for you in a cross-platform session in a cross-platform way. And this I found very useful. This I use all the time in my in my own code.
Nice. Nice.
>> So, yeah. Or return, I made it like wow, awesome. And I never use it.
>> But that's that's not the Like this is this is also what I know some some people like including [clears throat] myself tend to forget about like not always the destination is the journey. It's the It's the real thing. Like now you when you spent three six-hour sessions thinking about these problems and metaprogramming and how you can use macros, now you unlocked like just like a skill. And now when you're going to face another issue at work or in personal project or whatever, you know have oh, I have this tool in my toolbox I can use, right? Like if if you don't have it, you're not going to be like oh, let's do like, you know, three-level macro about backtick return and like it's going to work easily. Like you you don't You have to have this first like training to get an actual skill to then apply it. So, Yeah. And also I like you know, this amount of macro macros it surely has to slow down the compilation because you parse like expressions of every procedure body that you compile, right? And I like surely it's going to be slow. And the difference in my code base which is I don't I don't remember. Like I have a heat boxer. It's like 15,000 lines of code, something like that. And on top of that it compiles a lot of built-in modules, right?
And the overhead was 200 milliseconds.
Nice.
Imagine that in C++ land.
>> Imagine that like in C++ you include STD unordered map.
You go take a coffee or something. And you're done.
Yeah, yeah, yeah. So, I I don't know how like how they managed to keep compiler this fast. I I know you I know that Jonathan Blow constantly preach that computers are slow but still when you see the difference between or are fast. Okay, or fast fast, sorry. I was go I was getting ahead of myself.
Yeah, you just I know they constantly preach this that computers are fast. But still when you see the difference, it's just It sometimes it feels unreal.
And then he's like oh, compile times are getting slow.
Yeah, yeah, yeah. Yeah, I went through I felt in through an exercise in my job when I joined them. Like the project was compiling for 30 minutes. I was like this is I like I I have no I have no real comparison in my head like how fast the C++ project of this magnitude should compile.
But at the same time like I'm not going to just spend this time every time like I switch a branch or whatever. Like this is just like too much. And I I went through the exercise of finding out what to do, forward declarations, header including headers, what to do to avoid them. Blah blah blah.
I spent like two three weeks and I compiled in five minutes. It's like guys, like you've been working with this project for years. I'm not going to even like do the math how much time was lost.
And it's just Think about okay, you spent three weeks of your time. But it's like 25 minutes per person per each compilation that you save.
>> continuous integration system and >> Yeah, yeah, it compiles by a lot. Yeah.
Yeah, yeah. This is like probably hundreds of like years combined in in a very short time. And this is still and it's still five minutes. And like in Jai in Jai world like you get to like sub-second compilation times, which is just unreal. Yeah. Yeah, one of the things I really hated about compiled languages when I tried them first because I wanted to kind of escape a web dev treadmill for a while but one of the things that I hated is that I need to compile and wait.
And I remember I was like doubling in C++. I would make it like like a toy text editor or something. And like I press compile and I need to wait. It was like a couple seconds but still because in Python I can just I I see the results instantly, right? Or or at least for in JavaScript. And Jai kind of gives me the same thing when I can write three lines of code and press compile and see the result. This it just I know that And this is why a lot of C++ people they can like write a code for like 30 minutes without compiling it once.
And then okay, let's see how it go how it went. Compile.
>> But that's also like you need to go through this trial by fire to learn how to do it to keep all this context in your head not to like avoid. And also for the most part like you cannot really use some of just like standard library because this will in introduce so many weird things that will not show up as errors. So you need to like keep this in your head. Like for example like even if you use like a standard map or unordered map you need to have a hash function defined. Like good luck about remembering that if you're programming for two hours and you drop the map somewhere.
Yeah, yeah, yeah. So and I I try to find a balance before because at some point I realized that like checking out a result of your program every like five lines of code is also waste of time.
So yeah, yeah. It's something I had to kind of train myself to So okay, write at least like 30 lines of code before you check the output.
>> [laughter] >> Can we This was awesome. This this this explanation by the way for meta programming I think it would be super useful for people to also like get the uh get the understanding of how Jai meta programming works on a functioning example. A bit wild but still functioning example through all the like steps. So this is going to be super fun.
Now closing out this like impromptu session, can we take a look at the temperance?
Oh yeah, absolutely. Just like I don't know whether we'll be able to just read it through or do you want to How How long is it? How long is it actually? Here's the temperance, right?
It's just a text It's just a common file and it's 68 lines of code. Okay, so 68 lines of text. For context, okay? For context for everybody. When you and you get access to Jai meta, you get you get these how-tos. Exactly.
>> Yes, how-tos. Like that's the documentation basic. So we go through them and you kind of read like a little bit about strings, a little bit about memory management, and a little bit of this, a little bit of that. And then at some point you go to like 999 which is last one and it's temperance. I was like Yeah, and this is just a file that kind of Yeah, this is I think so uh this is like one of the important kind of parts.
Right? So at the time Yeah, so at the time of this writing the compiler for this language is about 55,000 lines of code.
Uh not counting comments and white spaces. The original source code for the 1993 video game Doom was also about 55,000 lines. Unclear if this counts comments and white spaces. It probably does. Look at this em dashes, very stylish.
Do some close planking blah blah blah.
It's probably a note to himself.
Uh whereas the compiler is likely to continue to grow, we will try our best to contain its growth. Constrain.
>> But as it stands today there is some kind of an existence proof. By the time your program is in the neighborhood of 5 50,000 lines, it should probably provide a large amount of interesting and novel functionality.
If it doesn't, perhaps it is time to ask questions.
And here, please try to write code that is small and does a lot for its size.
And yeah, I guess this is like the main thing.
Sometimes Yeah, this is the main thing.
Yeah, and Yeah, I don't remember if meta programming is here. I don't remember that. No, meta programming warning is probably in some other file but there was another one about like big meta programs. But yeah, it's just like this language it's you know, it doesn't feel like something that shipped you by corporation. It's it feels very personal. You have like a lot of like jokes and how-to and and and stuff like that like personal touches.
Also there's like a crazy one on uh allocators, right? You open a chapters on allocators.
And Okay, it's not here. It's it's memory.
200 Yeah, I think 200. Memory management. Yeah, and this is like chapter one. Yeah, yeah, yeah.
>> [laughter] >> Chapter one, the history of memory management.
>> computers were first invented, right?
Like when elves were first awoken in Middle-earth. This kind of stuff.
And you have graphs even if you if you like go down I think you have pointers like pointing to memory. It's like asky art like what happened like the problems like this is And it goes on and on and on and on and on and on, right? Yeah.
There's like a book about memory management.
>> This Yeah, this was the wild wild read but at the same time like this context is so like I don't know how to phrase this. If you want to learn this language it's different to just learn the syntax and what you can do.
Uh if you embrace this philosophy and also like read the comments and why things were done, you have this much richer understanding and then experience using the language. So Yeah. Yeah, for sure for sure. And uh Yeah, I mean I I like that when you get like a language its official distribution just tries to teach you I guess better like ways not only provide like a reference manual or something like that.
Nice.
Valigod, thank you so much for the impromptu joining [clears throat] me after for the stream.
It was very fun, yeah.
Thanks for inviting me. Any any closing thoughts? Where can people follow your work? Maybe people Maybe some people don't know what do you do. So maybe you know, mention your little channel.
sometimes post videos on YouTube like about programming.
I guess that's the main thing. It's like called Valigod Tech Tech Tech.
Uh and I also X account. Yeah, I should post on Twitter also like x.com/valigod and that's it.
Valigod or Valigod GG? It's just Valigod. Okay.
Yeah.
Nice.
That's I guess about it.
Nice.
>> Yeah, that's about it.
Thank you. Then stay please in the call right now because it will upload the thing. Just make sure that like we got the footage uploaded. For everybody who is in the audience the rules remain the same. The live stream will be available for members in this unedited fashion, the internet quality. And then once I get to edit this and go through the release cycle blah blah blah blah blah blah, it will be published for everybody. So if you are a member, you get the early access and you can watch this uh sooner or backtrack to see the full example of Jai meta programming. And if you want to what join Jai meta programming find an email and send an email. Find an email address and send an email.
All right. Thank you everybody.
Bye-bye.
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29
So What's Odin Lang Even Good For
TechOverTea
131 views•2026-06-01











