Conor

Welcome to episode 128 of Raycast. I hope I got that number right because I realized just as we went live that I didn't actually have it in front of me. But uh I think I did, and we have a very exciting episode today. We've got uh three guests with us who I will well, I guess I should mention them now. Actually, I'll mention them in a sec, but if you're watching this on YouTube, which I think is, I don't know what percentage of our listenership, but it's the minority. You can already see all three of their names. The audio listener, though, will have to wait a few more seconds. And uh I guess with that I'll do a brief infro introduction. Adam can go first, uh, then I can go. And actually, should we just change it so that we can all go around? Because I just realized that we're bringing back Steven. Spoiler for the audio listener, uh Stephen Taylor, longtime panelist, uh, has come back for this special episode. And so I was just thinking that I guess he should do the brief introduction. So maybe what we'll do is we'll we'll go around and we'll do brief introductions from everyone, and uh and we'll we'll go from there. So we'll start with Adam and we'll finish with me, and then we'll go uh Steven, Alex, and Jacob uh will do last for our guests. So uh kick us off, Adam. Yeah, I'm Adam Busewski.

Adam

Uh I am head of language design and longtime APL at Luck Limited.

Stephen Taylor

I'm Steven Taylor and APL and Q enthusiast and uh one-time KX librarian.

Alexander Underrainer

Hi, I'm Alexander Lontaner. I'm a Q enthusiast and the founder and blogger behind DEF CON Q.

Jacob Loveless

Yep, and I'm Jake Leblos. I'm a very longtime K and Q developer.

Conor

Awesome. And as mentioned before, or actually, I'm not even sure if I mentioned it before. Uh my name's Connor, host of ArrayCast. Uh fan of all the array languages, I'm very excited to hear about uh the topic for today. But before we get to that, uh I'm gonna hand it over to Adam, who I believe has three announcements if I recall correctly.

Adam

Well, we could call it four, maybe. Um, right. So uh first a couple of deadlines. On July 31st is the deadline for early bird 10% off special uh for the dialogue user meeting. You get that rebate because the schedule for what happens at the user meeting isn't quite settled yet. Only the workshops are settled. So if you're willing to sign up, even though you don't know exactly what the presentations will be, you get some money off. And also there's an the APL challenge, this uh introductory uh course slash competition where you can win some money for learning a little bit of APL and using it. Uh it has a round finishing that same day, July 31st. Um, then uh a couple of weeks ago we had a uh a workshop internally at uh at Dialog, and it was on using LLMs with APL. And uh so we're trying to educate our employees on uh on how to use LLMs uh effectively and safely. And there's an interesting blog post that we'll we'll put a link to as well on using APL with LLMs and how to make them do that, uh, then be able to write some sensible APL. But out of that came also an old project, something I started uh three and a half years ago, uh, when I was in parental leave and I was holding a baby with one hand, and then I was typing a little bit of JavaScript with uh with the other hand, and I made the bare bones a framework for a game that like a top-down dungeon crawler game that would teach you some APL. But I never had a chance to finish it because you know the baby grew up. Um and then I figured, well, as an experiment for there's a material for this workshop, I would throw the LLM at it and see if it could finish up the game. I think it turned out really well. Uh so uh this we'll leave a link to that as well.

Conor

Awesome. So links for all four of those things uh will be both in the YouTube description and the podcast show notes uh after I up this update this later. And with those out of the way, we're gonna do something a little bit different today. So uh because we have our former panelist with us, uh he knows much more about the uh you know K space, and uh we're gonna throw it over to Steven, and Steven's gonna uh lay the groundwork for what we're gonna be talking about today. And uh so with that, uh we'll throw it over to you, Stephen.

Stephen Taylor

Well, let's thank thank you, Connor. And let's start by frankly admitting that Alex and I screwed up.

Conor

Uh uh.

Stephen Taylor

He he and I are both uh romantics about the Q and K languages. And when the KX module manager appeared, we announced a meeting at Milden Hall in Suffolk for this September, uh, so that our people could get together and plan and start building uh open source Q packages. Uh yeah, that was a romantic vision. It was a wonderful idea. However, um KDB developers uh turn out to be actually rationalists, and they saw um what was actually quite obvious and what we didn't want to we we didn't really want to admit, which is that the price of KDB licenses restricts the language usage to some very deep corporate silos. And those corporate silos had no use for community code resources, and so we got very few registrations and wound up cancelling the meeting, and then something very significant happened, and um our guest today, Jake, did it, um, just I think the week before last, and it changes the landscape. And now there's still some kind of a meeting happening in Suffolk in September, it's emerging what it is in real time, but it's starting to look like ground zero for a QK Q open source community. Uh we're pretty excited about it. I'm not going to spoil I'm not going to um spoil uh what we're gonna learn from Jake, but um uh that's about it. Something's something really exciting is happening.

Conor

All right, so with that, I guess we'll throw it over to to Jake, and you can tell us uh about everything you've been working on and uh what you released uh just in the last little bit.

Jacob Loveless

Oh sure. Um so yeah, so like I said, my name is Jake Lopas. Um I've been I've been a K programmer since um probably very early 2000s, maybe 2000, maybe 2000, 2001, at a company called Appian. And then I um did that, worked for DOD, then I went to Wall Street, was on Wall Street for a very long time, and then I left um a little more than 10 years ago, and I was on Garden Leave, which I think is a very kind of garden leave is fantastic.

Conor

It is fantastic. I I've never been on it, but when I hear people are on it, I was like, the first time I heard about it, I was like, what?

Jacob Loveless

You're getting paid to do you're getting getting paid not to work anywhere else. You're actually getting paid to work in your garden. And um, and while while I was on garden leave, I was I started a project um to basically go rebuild um the kind of a K4 and a Q interpreter. And uh I called that L. And so um, and there had been kind of different versions of that all along the way, but about maybe a month ago, uh got to the point where I was like, hey, let's actually like post this out to the community, see if anybody else wants to play with it. Um so it's so L is a K4 compatible, Q compatible. Its goal is to be a drop-in replacement so that you can take kind of KDB style workloads and run it, you know, anywhere, right? You don't need uh all of the kind of as Stephen said, you know, can we can we kind of take this language and bring it to a larger community in a runtime that you know anybody can run? Um and so it was a really small group of people on uh basically a Discord server, and uh then we put up a website and then it got uh uh pretty pretty big pretty quickly. So I think we had like in the first two days, the website got discovered. Um it's like 48,000 people came to the website. We had over 300 downloads of the binary, so which is a good thing the binary is small, uh, because family small. So yeah, so that's that's the the thing that has kind of come out here, I'd say, in the last 30 days has been um people downloading the L interpreter, running K4 and Q code. Um for me it's really exciting to see not just you know everybody that that kind of I know in this community, but brand new people coming from completely different backgrounds. Um like I had somebody last week who emailed to the list group and they were working on telemetry data for um effectively cars. I had somebody who emailed that was working on um like biogenomics um and saying, hey, you know, can I use this for this? And I was like, yes, it'll be great for that. You know, let's talk about you know how do you restructure these kind of problems in an array-oriented thing. And um, by the way, it turns out that that KK and Q just absolutely crush for that kind of workload. Um at uh we built a rag, uh, which is one of these AI vector search things. It was like 20 lines, um, and really, really, really fast. So yeah, so that's that's what it is. And and it's got a public website, it's at lv1.sh uh because you needed a a short domain, um, and that's as short as I could get it. So yeah, that's that's the big big out there in the open.

Conor

Yeah, so it's uh very exciting. I did see, I think I saw it first on uh the APL JK Reddit. It was posted there by someone. And uh very exciting. But I so I guess the I mean there's a number of things we could talk about first, but uh probably notable um is the differences, like the runtime differences. So do you want to talk about what L offers that uh you know the previous interpreters like because they're and they're not exactly like it's a drop-in replacement from like a what do you call it, language level point of view, but from a runtime point of view, uh there are some differences, which I'm sure uh people listeners of this podcast who are you know programmers, some are maybe not programmers and just curious, but uh I'm sure a lot of the listeners would be curious to hear those differences.

Jacob Loveless

Yeah, I mean I it it needed to be um language compatible because you know, frankly, I have 20 years of code. I didn't want to rewrite. Um that said, I I did want to go experiment with you know kind of new ideas under the cover. And I and I think the big ones are um, well, the first one, which is pretty straightforward, um, is just SIMD, right? You you you want to actually get every cycle out of the chip that you can. Um so take all of your primitives, um, you know, sit very quietly and make sure that you can implement SIMD versions of that. Uh then once you have that, I wanted auto threading. So uh K4 had a concept of uh peach, of parallel each, um, which is wonderful. But I you know, it kind of changes the code. So I wanted like um, you know, like a reduction like sum or something like that to actually automatically thread over the array and you know, kind of do that that map reduce concept, but do it completely transparently.

Adam

Um does uh K not have any guarantees of stability of results like that?

Jacob Loveless

Or with regards to floating point?

Adam

Of what? Yeah, floating point, yes.

Jacob Loveless

Yeah. Um I don't really know what Kd B has. Um L's floating point is there's effectively a like a comparison tolerance that that comes out. And yeah, if you sum them in different directions, obviously you would get different values. So um so the reductions are are taken in chunks, but the comparison tolerance is uh I think it's it's 18 to the negative 17. So it's yeah, as you get far enough out there, um, you can get different answers, but kind of the interpreter itself hides that comparative comparison tolerance at a at a certain level. Did that that answer your question? You get the same answer every time, um, but it because you are paralyzing and reducing reducers, right? You you can if you would get something different than if you were seriously just walking. Yeah, yeah. Yeah, just like you would get something different if you reversed it and walked through it.

Adam

Yeah, and we I'm asking because we have this problem with dialogue. Our summation code and interpreter was written pre-SIMD, and uh and now we can't change it because we we our customers want stability. You don't want the amount of money in people's bank accounts to change because we changed the summation algorithm. And uh yeah, you might ask why people are using floats for money, they are like well.

Jacob Loveless

I I think well, if you use if you use floats for money, you should really think very carefully about where your life went wrong. But um that that is actually kind of a good segue to last thing. So the last thing was this idea of I mean, I call it compression because I can't think of another more elegant way to explain it, but can you take quantitization is maybe another way to say it, but basically, can you can you take this array and can you store it in a different format that allows you to work on smaller uh memory footprints? So can you can you change underneath the covers, can you change, can you compress that array into another format? And then most importantly, can you work on that compressed device? Can you can you make all of the array operators, can you make all of the verbs and adverbs work on what I call computer and compressor? Lots of people call it computer and compressed. Um and when you do that, you could do something like if you are storing money as floats, like behind the covers, L doesn't store that as a float. L actually goes ahead and promotes that into an int, um, and then kind of does this very clever little trick underneath the covers um to allow you to operate in the int space and then gives it back to you in in the floating point space, um, or the real space, depending on. So um so those three things, kind of the the SIM D, the auto-parallelization, which is different than SIM D, um, and the compression, those are probably the three giant pillars that are really fundamentally different. I mean, compression, compression, I started doing compression a couple years ago. And it was uh it was enough of a performance improvement that I actually had to delete everything and start over. Um, because you basically changed the entire uh representation of the object. But it turns out that that is the unlock from a performance standpoint. Um, you can really only make these things go so fast in SIMD, you can only make them go so fast, you know, across multiple cores. The I mean, bandwidth, memory bandwidth is the enemy. So you know, I say this all the time, but making things go faster is actually pretty simple. You just move less data over a shorter distance using a more efficient protocol. So um if you can take that array and move it into a smaller type, um, you can move less data. You know, you have to be very cognizant of making sure that where that array is relative to the core that it's going to operate on, that's your shorter distance. And you know, really the protocol you can think about as the actual operation, the CIMD operation underneath the covers. So those those are kind of the three crazy, crazy ideas.

Adam

Um doesn't sound very crazy. I misunderstood when I was reading up on this. I thought by compression you actually like compressed data as in zipping it, but it's not. You're just talking about using data types.

Jacob Loveless

Yeah, dictionary compression is a really I I don't think really helpful. Um, because you can't really operate it on it. You can't really operate on it.

Adam

I I think well you you could like let's say you had a matrix stored as as some vectors and it was fairly sparse, and you actually compressed each row separately, and then you want to reverse the order of the matrix, this you can do without decompressing the components, right? So I that's that was the idea I got when you when I heard about like compression, it's like, well, how in the world do you write algorithms to operate on the compressed data? But if you just mean data types that are more of more dense for the data that's actually there, then that's pretty regular fair for array languages. I I thought that every serious array language already did this. And if obviously you can't tell me about the source code at uh of of official KQ, KDB. Um I would I assume that that was happening underneath the cover there as well.

Jacob Loveless

Well, well, I think in a like like let's take a simple example, probably the the easiest codec that there is to kind of you can kind of almost see it in your mind is the the frame of reference, right? So imagine you've got um, you know, I don't know, 255 plus till a thousand, all right? Or 255 plus iota a thousand. Um so now you've got this big array of 32-bit integers. Um frame of reference basically says find a minimum, right? Store that offset as the base, remove that from everything else. And then the question is now you've got a base, and then you've got a payload, right? You've removed the base from the array, and now you've got a payload. Is there a bit width that can represent that payload smaller than the original bit width? And um, and it turns out that the answer is yes, that happens like all the time, right? You can, you know, you might have an array of 32-bit integers that you can represent as you know, as a short. Um or you know, if you kind of take frame of reference and apply delta on top of it, you might actually be able to get that down to four bits, right? So, and you know what's really nice about frame of reference, aside from the fact that it's kind of easy to see in your mind, is if you make everything do that from the beginning, then you kind of get these free little performance wins just by the structure of that. So, uh to give you an example, let's say you wanted to add an atom to that array, right? Well, obviously there's no reason to do that element-wise. If you're going to add the atom to every single value of the array, you would just add it to the base. Um so these kind of operations become faster. Um, also, when you when you kind of sweep to go do the bit width calculation, you're gonna get some pretty useful metadata that's gonna fall out for free that you might want to actually stamp on the object, right? So um you you know, certainly you're gonna get the range, right? Um, and again, as you kind of do this consistently, what you start to find is you know the performance wins stack up like a lot.

Adam

Yeah, I understand a lot a lot. So it's it's I just I just remembered now. What I what I understand from you is uh is that you're doing this aggressively, you're doing every basically taking every data type that exists, uh, and and and trying to combine. So I I I know array languages traditionally do things like this, but they tend to restrict themselves to a few types rather than every possible type.

Jacob Loveless

Anything worth doing is worth overdoing. Um so yeah, it happens.

Adam

There was a uh there was a talk by Simon Garland that spoke about differences in uh in how in the implementation of of KQ and APL. And he said that there were uh APL traditionally has bit booleans, right? But that requires a lot of fancy uh bit flipping work to to make all your algorithms work, but it does create a huge difference in in performance because I mean at worst, an eighth of the uh of the data going across.

Jacob Loveless

But then when you want to do something like you know, get the average of a Boolean array um to give you like a probability, then you know, then you have to kind of start going the other way.

Adam

Well you don't have to put you uh explode it up to to bytes because you could in the inter the the processor has pop counts, right? Yep. So there so there are lots and lots of fancy tricks you can do, and then and then the processors have like APL functions like expand and compress and things like that. Uh and that that they can they can do. But remember, he spoke about that's where I want to get here. He spoke about the changes or the the differences in how you design the language based on how it's implemented. And I thought that was really interesting that because K doesn't have bit booleans, there's no point in having a primitive built in verb, whatever you want to call it, uh Of compress rather you just use indexing with a where right so you convert the Boolean to indices, and then at that point it it you lose a lot of uh of the length because all the zeros go away, and you're not you at least if it's shorter than 256, uh then then it's not going to blow up the type for the indices being there. Everything is every element, every Boolean is one byte, so it doesn't make a difference. And and so you don't need a compressed function, therefore k doesn't have a compressed function, it just uses indexing wheelware. Whereas APL that does have bit booleans, does have compressed, and it's a huge waste to blow up a Boolean that's already packed to uh integers before you do that. So now here's the kicker then. If you aggressively pursue all these internal representations, such that yeah, I'm sure you do have bit booleans, then and but isn't the language then like doesn't it fight you in that way? That it that you it for the the way people write the code forces you to blow up your your beautiful bit booleans to ugly big integers.

Jacob Loveless

Yeah, and so you are describing essentially the three-year nightmare of stepping back and saying, Okay, all right, this works. What of these what of these verbs and adverbs do I need basically result in um in materializing? And then you just sit there very quietly with a giant yellow notebook and um and you knock them all out. And um you can't knock all of them out. Um so like some of the transcendentals, obviously, you do just because of kind of the nature of that, you do need to materialize them. But then then you start thinking about well, do I need to materialize the whole array? Or do I only need to materialize, you know, so I can move the array in into the cache line, but then when I'm doing the operation, I have to do a small materialization. I can uh you know, maybe store that in a scratch offset. Can I can I still save some memory bandwidth moving over? So the ideal scenario is um, you know, kind of a closed form of computer compressed. You want to get all of those that you can. And then, you know, worst case scenario, you want to get to to kind of a partial form of computer compressed, where you're like, all right, well, at least I'm gonna move this small, this, this much smaller thing over the memory bandwidth, but then I I am actually gonna have to work, kind of uh, you know, allocate a little space on the stack. I'm gonna have to explode this thing up and do a little bit of work and take it chunk by chunk. But um, yeah, Adam, I actually have a like a grid of all of the verbs, and I can I don't I don't know if I have it in front of me, but I can send it to you where it's got all the verbs, and you can and you can see kind of over time where it goes from basically red where you had to materialize to green where it uh where it operates compute on compressed.

Adam

Um so so you're saying okay, so you're also aggressively using things like arithmetic progression vectors for the for things like indices. So they stay small. Yeah, but do do you also I don't know if it's a universal term or something? There's something at least in the in some area, some people use the term thunks, where the where the language does not actually evaluate some code, but rather remembers that this verb needs to be uh applied to this noun, but doesn't do it until necessary. So for example, you you you could do that. Let if somebody does a where on a boolean in order to index, then you wouldn't do the where on the boolean. You would remember that this where needs to be applied on this array, and then when you get to the index indexing, then the interpreter goes, Oh, wait a minute, indexing on something where where needs to be applied on a Boolean. I know this, that's just a replicate. So then it goes in and directly takes the Booleans and does the filtering and skips the whole materialization of the indices.

Jacob Loveless

Yeah, there's no kind of delayed compute there, but or at least not in L. Yet. But it does have a concept of fusion. Um so fusion, uh, you know, fusion I think is a really loaded term. Um uh Rick Sony works with this on me. Is so fusion means different things with different people. So for the easy case, it basically means no intermediates, right? So if I um, you know, if I do whatever some square root x, right, can I can I do this without creating intermediates, or better yet, would be like a chain of functions where it's you know array uh where the output is array, array, array.

Adam

If you if you do two plus three times times an array, right? So then then since you need to loop over the array to do the the three times, you might as well do two plus three on each one separately.

Jacob Loveless

Yeah, and then like then you just hate yourself.

Adam

Um so but how do you do that without being lazy?

Jacob Loveless

Yeah, so essentially underneath the covers, um every array you can you can borrow basically you can think about it almost like copy on right. Um so when an input comes in, it it can be uh kind of borrowed, which means you can mutate it, or it's you know, it's effectively you're operating on a copy, and then you can just mutate the intermediates, and then you don't um then you don't really have those intermediates. You know what I'm saying? You're not you you're kind of working directly, you're literally mutating the the input comes in and it's like, hey, this is safe to mutate, you do square root on it, mutate it in place. Oh, right.

Adam

You you mean you're having a you have a ref count on the arrays, right? If the ref count is one, you know you can do it in place with it.

Jacob Loveless

Yep. Um and you kind of have to do that way up in the beginning. And then that's the other concept of fusion is this idea of hey, we're going to, you know, if we detect, and there's the this is done in L, like I think it's done pretty much everywhere else, which is just basically with uh kind of a table of known operators. But um, if you see this, you know, kind of bytecode type, you this structure of bytecode, let's go ahead and replace it with this other function, right? So um and and L does that in its fuse.c implementation. So it it uses actually it looks very similar to LuaJet from uh Mike Paul's. So it kind of looks at the bytecode and goes, aha, you're doing um, you know, you're doing where, you know, where array greater than x. Um okay. Uh there's actually a different kernel for this that we're gonna we're just I'm just gonna like swap out that byte code and replace it with this other one. It's gonna be a lot faster.

Adam

Uh but again, if you do where arrays greater than x, I mean if you're just naively executing this this code, then you see the the comparison, you do the comparison, then you get to the where. Surely there must be some amount of laziness for it to even recognize the pattern. There's there's no laziness.

Jacob Loveless

It will actually Rick and I talk about working vertically versus horizontally. So you might want to, under certain operations, instead of doing uh the whole vector A, then the whole vector B, then the whole vector C, you actually might want to flip it on its side and do, you know, operator, operator, operator, operator, operator, operator operator. Yeah, mate. That's the fusion meaning. Yep. And so um we'll swap that out.

Adam

That that little bit will swap out um so the interpreter reads ahead of what's going, what's coming?

Jacob Loveless

That's how it's well it just looks at the bytecode. So um when you write when you write the function, right? You write foo, whatever.

Adam

That gives you the bytecode.

Jacob Loveless

Yeah, and then when the thing goes to the generating the bytecode, it's like, okay, I've made this bytecode just the way you asked.

Adam

And then people I think I think I think you get it.

Jacob Loveless

Okay, so you so there's a it's not as complex as as as as well. No, no, no. I think we get it there.

Adam

So there's a it's sort of like halfway halfway compiled, right? Then the interpreter goes through, take, takes the code, converts it. I suppose it builds some some AST internally for the function that that these and then it recognizes parts that the branches on the tree, and then says, Oh, I know this tree, this tree branch. Let's change that to something else. There you have an advantage we can't do in a dialogue. Yeah, because we're not statically parsable.

Jacob Loveless

That's actually how I mean it unfortunately it does have to do it in a two past, but it doesn't really matter. Um but yeah, it's that's how my call does kind of legit in in a lot of ways, is kind of looking at the intermediate representation, and that's where the that that's where the swap out happens. So I, you know, and I think that's kind of the fun part. It's nice to have the restriction of this this code must run this language standard, and you're like, but I want to do this. And it's like, all right, well then you have to you have to do it without changing that code or changing that language, right? So um, so you know, fuse.c, which kind of does that walk over the over the interpreter, over the bytecode, or you know, the actual object storage, where it's like, I'm giving you an array of dates, and it's like, okay, I'm I'm gonna tell you it's an array of dates, but I'm definitely not gonna store it like that, and I'm not gonna operate on it like that. Um and so I think you know, these little things, they I mean, they stack up. Um, I've I've gotten reports in the field. I think the the worst report I have from the field is that it's six times faster, and some of the best reports are just insane. But um again, there's no magic trick here. It's just there are some there are some places where you would probably want to change the language, although I'm nowhere near smart enough to write a better language. So instead, you just go, okay, well, I know that this combination of operators is more efficiently done this other way. And so I'm gonna put that in my fusion table. And then if I see that bytecode, I'm just gonna swap it out with this one.

Conor

Um so if I understand correct, this is super um, super fascinating. Uh and it was interesting too when you were listing off like the major three things, you left out the fusion, uh, which I was like, wow, like if fusion doesn't fusion doesn't even make the top three, like that's uh that's pretty crazy. Um go ahead. Yeah, yeah, four. Um if my understanding is correct, then so uh with the ref count um basically reference counting, you avoid like the unnecessary allocations, which is like the biggest win. So does but does that mean that the like the luogit, not that that's what we're calling it, but you know, the that kind of mechanism that's doing that fusion, if that doesn't have uh uh you know a pattern recognition for a certain thing, yeah. Is it is it then like so say in the example that Adam had where it was you know plus X, you know, times Y or whatever, if it if it didn't, I'm sure it does have uh you know uh uh recognizes that and then replaces the the bytecode. But if it didn't, does that mean that you'll avoid the allocations, but you might end up iterating still the number of times the operations? So but like you basically there's two pieces you can expect to avoid allocations because of the reference counting, and then the uh the bytecode uh pattern recognition or whatever you want to call it, um, that's the one that like fuses the operations. So it's kind of like two pieces. You can get you guaranteed like your reference counting if it's one, you'll get that piece, and then it's just a matter of uh it recognizing. I mean, that's very and on top of honestly, I had never not to switch completely topics while I'm talking, I'd never heard of this uh because Adam says, Oh, you know, I think most languages, I had never heard of this kind of like separating or like compressing uh data into a smaller bit width by like basically storing a component of it. And then like it's very it's I don't know, it sounds novel to me because I've never thought about this, but then when you were like, oh, you know, if you just add a number, you can just do it to the base, and I was like, that's crazy. Like you you turn what, even if you're gonna use fusion, like because that's typically the way I would solve that, right? Like there's a an array language called cap um that is implemented in Kotlin and it's a lazy APL. So if you do a plus one or a plus X, it just it'll defer, it won't do it. So you you know, you're you're not gonna pay like a linear time for that operation, it'll just bundle it with whatever it needs to down the road. But in your implementation, it's just an O one operation, like who cares? Um and like that then my my my my my brain is like how many different cases like are there like you know uh tricks like that where you can turn you don't even need to fuse anything, like you can turn what would be an ON operation into just like a constant time thing. Um and Adam, you said like like this is classic, like this is a lot of interpreters do this kind of thing. Like, I don't know.

Adam

So in APL land, I it for commercial, like a real APL implementation. I think it's unheard of to not do um type. So this doesn't have a name though. That's the thing, like Jacob. You you were saying that we call it squeeze internally, but the APL never ex sees this, right? You don't you can't it's not directly observable unless the vendor puts something into the language that lets you observe under the covers. So we have something. Like we're at dialogue. I can show you that dialogue has something called quad dr data representation, and it will tell you uh the what the internal representation is, how many bits per element and what type uh it is. And you can see that if you uh if you give it a one, if you give it one Boolean, you will say it's a byte. It doesn't bother to make it a bit because you're not gonna save anything. If you then connect that, make a vector of two bits, then it will squeeze it down to a single byte. And it's just using it has a length field, so it just says, okay, only the first two bits of this byte are actually the data that we're using right away. You cannot really stop it from doing that. Uh I mean you can, you can you can tell the interpreter don't don't squeeze this array, but it's not gonna stay forever, it will only be as until it finds that it's convenient to do it anyway. Um, and it yeah, it's aggressive, it does it all the time. And even though there's so many checks for every operation, do another check, what can we now squeeze? It it sure saves time. It would be unbearably slow if if you didn't do this. And the bit bit Boolean algorithms are are super optimized for do all kinds of crazy things.

Conor

Did you say Jake? That because you it sounds like you've well, I mean, I guess you didn't come up with this idea. I mean, I'm hearing about it for the first time today, but apparently lots of folks know about this you know for decades. But like you've taken this idea, pushed it to like you know 110%. And um would you say like of the four different things, this is what gets you the the largest percentage of the game? Like because you're saying you basically went back and rewrote you know most of the language, if not all of it, because of this.

Adam

Um that's really interesting too that that that's the main thing because if we I can tell you in dialogue has bit booleans, and then it has got one, two, and four-byte integers, and then we've got uh 64-bit floats, and and we have a crazy uh decimal uh 128-bit flows. We've got some two times 64-bit uh float complex numbers, and and even for characters we do this. So even text data will be the one, two, or four-byte uh per character. If you're writing ancient Chinese text, you think you're gonna end up with four bytes per character. Um, I know that APL plus only has a single integer type. It does do bit booleans, I think every APL does, um but then it just goes up to a full uh I don't know if it's 64-bit or 32-bit integer type, and then uh and then they have floats. Um and yeah, I didn't know that being so aggressive about the types would make such a big difference. I knew that it does make a difference to have this sort of thing, but certainly we don't do uh two-bit integers and four-bit integers.

Jacob Loveless

Oh yeah, it makes all the difference in the world. Because the you know, I think the thing that is different today than you know, whatever, 20 years ago, more than 20 years ago when Arthur did uh K is the the CPUs are fast, but it's the memory that's slow.

Adam

Yeah, yeah, that that's that's well recognized.

Jacob Loveless

Yeah, and it's it's I mean the memory bandwidth is just fighting you everywhere along the path. And so, you know, again, you just you gotta just move less data.

Adam

So for all the mathematical verbs, yeah, they are there libraries out there for like four-bit integer multiplication things like that because it's it's going to be a crazy mess.

Jacob Loveless

Yeah, it's a mess.

Adam

Yeah, it takes years, yeah. Like, yeah, because either either you blow up every time you do something, you blow up to then you might as well not store it like that if you're not changing up an hour. So you have to you have to do have to stay at your type and still do multiplications at every width and additions, and uh etc. etc. That's yeah, uh huh. No, you have to some people described uh array languages and ascribed it for AP described for APL but it would be the same across the mole, that they're sort of like code libraries. You have some people, very clever people, working for many, many years to write all kinds of extreme algorithms for doing things well, and then you just use a simple symbol, a glyph, and you get all that hard work.

Jacob Loveless

Yeah, and there, I mean, there are some libraries that do things like um kind of fixed point arithmetic, and um uh there's a there's a GNU library that's you know kind of really good about uh but I mean at the end of the day, uh none of that stuff really helped. Um papers help, but you know, eventually you gotta roll up your sleeves and just do the implementation. And the trick is since you can't change the language, um you have to think about making the codec uh standard, right? So even though there's a bunch of codec under the under the covers, they all effectively share this concept of like a base and a payload and then a patch. Um you don't need a patch for frame of reference. But um yeah, you can you can I I will get you the HDML document and you can see what's left. Uh I think the only ones that are really left are the transcendentals. You have to do them partially, but um but um you have to do them partially if you're not doing the fast math versions.

Adam

Um also helps you that language has a small vocabulary and not so mathematics oriented for that for APL this would be a nightmare because of all the fancy built-ins, and for something like J, it would be well I it's funny.

Jacob Loveless

I I think I think if you I am not a language developer, I could never write a language, I do not have that much um creativity and elegance and foresight, and I don't have any of that. I'm a mechanic. Um, so but the simpler the language, the the more you can do with it, right? So, you know, again, I've mentioned him a couple of times, but like Mike Paul's Lua Jet is I still think one of the most underappreciated pieces of code. And the the reason why you can get away with it is because Lua is so simple. Um Q is actually very messy, but K itself, I mean Q is built in K, but K itself is actually very simple and super elegant, and it's not a giant surface. So if you can, you know, if you start with something simpler, you can you can actually squeeze a lot of performance and you can do a lot of these tricks. Um because it's a nice, well-bounded framework that you're gonna work inside. So um, and yeah, you can in L, you can, I mean it's not I mean it's not hidden, you can do it, but you can do negative 17 bang. Negative int bang is kind of the KQ world of I've got this function, but I don't know what to call it yet, or something. Um, and you can do negative 17 bang and you can see kind of what is the object stored um into like how many bytes is is the object compressed, which should always be yes, and then how many bytes is it actually storing versus how many bytes was it originally? And you know, the other thing is again, this is not a like K and Q and and L they are not show horses. They're workhorses, like they're not they're do to the you know, these languages are built to do very specific, very kind of distinct workloads, and you know, database style workloads and financial style workloads, and so you know, you don't you don't have to you have to be able to solve those problems. Um, you don't have to be able to solve all problems. So I I mean again, uh K always had a concept of a comparison tolerance, and that's like you know, I I don't know if that's how it works in a APL, right? If you've got two uh 64-bit floats and they're almost the same, but not exactly the same, like at what point do you say those are equal?

Adam

Um APL is has at least for very long time has had has a configurable um comparison tolerance, that's what it's called, and as well. But I know J's is fixed. You can I don't think you can you can change it. I suppose case is also fixed. I case case is fixed, L's is fixed, um and it's it's a is it a multiplicative uh comparison tolerance? So it's like there has to be a factor of of one plus ten to the power of negative seventeen maximum ratio between them, right?

Jacob Loveless

Yep, yep. So which is almost a shame because then you can't really do the uh then you can't just do the mem compare to exactly.

Adam

Yeah, that makes that makes Load operation is much, much slower. And you really it would be sort of nice to not do that.

Jacob Loveless

Unless you've got a compression codec that kind of knows that from the beginning, right? Um sorry, Steven has his hand up.

Conor

Yeah, I was gonna say hop in here. And also, too, we've got two questions in the the chat. Um, so uh we'll probably ask those in a little bit. Uh but yeah, if you have questions, feel free to cue them up and we'll make sure to to get to go to those in a bit. But yeah, Steven, go ahead.

Stephen Taylor

Well, look, Jake, we've spent a little time exploring the implementation of how you manage to get ahead on performance. Uh and I'd like to ask you a version of the question I was asking you the other um the other day on our call. You've got an interpreter that has 100% coverage of the key language uh and at least as much speed to put it to put it um mildly. Um, what do you want for this language? Um, that's not I'm not asking for a price. I don't know what you want to happen first.

Jacob Loveless

No, I think you need um we need more K and Q developers. We need a giant army of people building great systems, great code, and it needs to be out there. Like I um, you know, recently we've been doing a lot of work with kind of AI folks, and you know, it's like, why did Python win data science? Um, this is pretty easy because everyone used Python. Um, and there's a million packages. Um, you know, sci fi is amazing. Like, I mean, it's it is, it is actually amazing, but boy, is it slow and boy is it verbose. Um, and I think, you know, I think there were really two problems here. One was, you know, unless you were kind of a member of the Illuminati, getting access to these interpreters was very difficult. Um, and that that that that obviously needed to go away. Um, and then I think the second one was, you know, even though you know people like the bro have done great work on documentation and books and implementations, uh there there wasn't if you came, even if you had the interpreter and you had some base knowledge like Q for Mortals or something, um, it it's still difficult. You kind of learn this thing, or at least I did. Uh, you know, this language was kind of passed down like a secret from one person to another. You would learn, you know, uh, and I think that LLMs are making that go away. You know, you can you can ask, whatever, sub your favorite LLM in, but you can ask your favorite LLM how to do something in an idiomatic way, and you you tend to get right answers. And I think, you know, I think of the LLM as like an infinitely patient teacher, right? So um now it's not perfect, but you know, as as I always say to people when you have new technology, it's like, hey, just remember, this is the worst it's ever gonna be. Um, so you know, and especially in the array languages, you I I don't know about you guys, but I I have always said it's like I will go think about something for hours, hours and hours. And then it might take me five minutes to code it. Like the actual act of writing the code is never the hard part. Like, never. Like the language is so simple, you learn to think in that structure, you know, you start to recognize patterns. Um and you know, whereas like you look at today and it's like, you know, oh, people aren't thinking at all, and this LM is just vomiting out this, you know, truckload of Python that's gonna slowly set the world on fire uh through its inefficiency. And it's like, hey, hey, hey, hey, can we get back to like a craft? Like, we actually some of us actually want to do this as as an actual craft. Can we get back to thinking about and then you know, writing less code, reading less code, debugging less code? Like, can can we get back to that to that world? I I don't know. I mean, L soup to nuts is I mean, and it's a lot, but it's maybe 12,000 lines of C. And you got to keep in mind that every line of C can only be 80 characters because I am absolutely crazy. So um the you know, how do people how do people debug million lines of code? I have no idea. I mean, debugging more than 500 is just like takes me all day. So uh I I like like small shortcuts. So can we can we get everybody an interpreter? There's I think there's a lot of great um education documents out there, and people, you know, you should start playing with all ones. Like they can you can ask it to write idiomatic cue, and you know, it'll do it'll do an okay job. Um, and again, today's the worst it's ever going to be. Um, and so you know, I I I'll give you a great example of this. Um I now that you have an interpreter and you can kind of run it anywhere you want, um you can make that a tool call. So you can take this very, you know, kind of maybe an LLM that doesn't write great code, and you can let it call the interpreter and just iterate, iterate, iterate, iterate. And then it, you know, you can fine-tune it till well till it learns how this works. So um, so yeah, I think those are kind of the the main goals. And also I think, you know, I I think it's awesome that everybody, it seems like every single person right now is like, I'm gonna go build a language. And like, man, do I honor that? Um, but there's something to taking a language that has a big footprint. I mean, it has a bigger footprint than I think people realize, um, and just making it faster. Like, you don't actually have to go build a new language. Like, why would somebody continue to do work in K and Q? That's like it's still got to be the bleeding edge of performance. Um, yeah, I mean, it's amazing to me how how fast K and Q is for the you know, the style of workload that it does. Um, and you know, we're talking about effectively almost 20-year code. Um, I mean, I'm sure there's lots of improvements that have happened, but fundamentally there's it's it's 20 year 20-year-old code. Um so can you get another order of magnitude? Um you know, and that's not just on the language side, but really, guys, the the database is what makes this thing live, right? It's the database workload that people buy it for, use it for, implement it for. Um and you know, can you do can you be an order of magnitude faster than other things? And it turns out, yeah, you you can, but you have to, you know, make it small and it's binary sizes matter, like iCash matters, like um, like these things all matter. These are all parts of the craft that I think somewhere along the way got lost. Um, maybe everybody should, you know, go back to having 256k dial-up to to force force a diet, like a GLP one for computer science. But um yeah, that that that that's kind of what my thoughts are there. So right now it's uh can you make it faster than everything? It's it's pretty far on its way. Um even on the database side. I don't know if you guys have ever used DuckDB. DuckDB is an amazing, great piece of code. And it by the way, uh Adam, it has some of these compression codec concepts built into it, but for database workloads. Um, so um I think Duck uses for its loading point, I think it uses uh um ALP, um, which is basically you take your uh, you know, take whatever ill-gotten youth handed you uh money in decimals. Um this basically takes that and says, okay, well, we're gonna write a compression codec that's gonna effectively raise things to the power, you know, raise things to different powers of 10 to see if we can um get this guy up in the integer space.

Adam

And then of course that's that's really interesting. Yeah, and then of course that means you have to have some fuzz, right? Because a lot of things will be almost fit if you raise it to some power of 10.

Jacob Loveless

There's a really good paper, the ALP paper, which is out of, I think um the CWI group, CMI group. Um we could put it in the show notes, kind of describes this. But you know, I think I I don't I don't know about you, but like I'm I am a small small little things and then interlock them, right? So you could even think that concept, right? So say, so say, you know, Timmy hands you an array of of US dollar in floats, um, and you could just raise that to a power of 10, um, and and everything would be okay. But then if you were to interlock that with the frame of reference, right, and remove that base off um and now take that payload. Well, hey, those two codec interlocked together actually give you like an insanely efficient way to work in the integer space on a smaller bit. Well, you know what I'm saying? Like these things all get interlocked. People, I think people, you know, would look at um kind of especially if you if if you looked at like some of the stuff that that Arthur did make open, it was like, oh my god, this interlocking mess. And it's like, no, no, no, no, no, like that's exactly how you want to do it. Like, if you have one function that's not interlocked with something else, you gotta ask yourself, do I need that function? Um, or is there some other way to tie these guys together? I mean, there's literally uh on the on on the L kind of to build L takes a long time because it runs all these tests. And one of the tests is um essentially going through and looking at the assembly gets output for every function. Um, that can often be inline and other functions, but making sure that they all fit within the iCache, right? And if it isn't, then you got to go back and be like, all right, is there a way I can shave off you know a few bytes off of this thing because I know that this is gonna be interlocked into all these other places? So yeah, I don't know. I that I went on a little bit of a diatribe there, Stephen, but that's that's a goal, right? More people using this language, doing this craft, and like, please, for the love of God, stop handing me pages of code and then be like, Can you find my bug? Um, it's like my answer is always like, Yes, I found your bug right away. It's this entire page of code. Um, you know, give me give me 20. The rag engine that I that I built with, you know, for for these friends. Um I mean, it's 20 lines. It's 20 lines, and it's way faster than what they were using, which is this giant commercial product. And it's like, okay, it's 20 lines. Like, we can all read it. Yes, yes, there's some complexity here because they're dense 20 lines, but like we all can read and understand this. Like, you can actually map it in your head, versus the other thing, which was like, you know, I don't even know, tens of thousands of lines. I was like, dude, how will you ever find the bug here? Like, or or by the way, finding a bug and optimizing it are just whether or not you admit it's broken, or it, you know, you don't admit it's broken. Like if it's slow, it's still broken. So, you know.

Adam

It's it's interesting. You say this about the amount of of code and and the problem. A problem with LM is that people are spitting out giant amounts of of code. Uh, what I found, uh, so I I had uh I'm going back to what I said right in the beginning when we before it introduced our our guests and this uh this game that I'd made, and that had written it in in JavaScript with one hand, um, because the other was on the baby. And uh so by necess by necessity, but also because that's how I like to do it, I wrote it in a in a special she was a variant of JavaScript that I like to call Arthur Whitney JavaScript. Um where uh I don't know if Arthur has ever actually ever written any JavaScript. Um I would ask him if I if I met him. Um but but in what I imagine it would look like if he wrote it after having seen some of the code. Mind you, I don't understand C, I don't read C. Um, but I've seen some of the things he has written, and I figured this is how we'd write it. So uh one letter variables, two letter variables when necessary, and no unnecessary white space, keeping as much as it's keeping the code visible on the screen at one any given time.

Jacob Loveless

Um you can actually Google Arthur's JavaScript. There's one called C dot JS. Yeah, it's the the connector. Um, it was the basically the IPC protocol uh parser in JavaScript. C.S. You said C dot JS.

Adam

Oh JS, yeah.

Jacob Loveless

Yeah, I'll I'll see if I can find it.

Adam

But um, so this is how I like to write my JavaScript in general. I also relied on every quirk available in the uh in the browser's JavaScript engine. That might not be the best idea uh to do that, but it makes my code shorter because I don't know. People people have told me that you need to use things like const and let and var and don't know what in in in JavaScript. I don't know what these words do. Apparently, my code does the same thing when I don't write it, so I don't write it. Um and um, but my variables only survive very short before they're anymore. So who cares if it's the global scope or whatever? Um so so so this is how I write it. And and the interesting thing is that I was able to get, I was using using Claude, I was able to get Claude to stick to this. So I did make it first got rid of all the quirks because apparently there are some features that need a JavaScript that are not available in quirks mode. Um, but other than not writing super quirky code, so everything is sort of best standards, it still looks the same, still makes actual JavaScript programmers go all uh white in the face when they see it and say, for first reaction, that's not JavaScript. Second reaction is oh wait, that is JavaScript, but what are you doing? You're not supposed to write code like that, and that's fine. Um, but I was able to make Claude keep doing that, and that means that my whole game is like I don't know, 250 lines of of JavaScript, something like that. Um and I think it's and then I can I can actually go through it, even though it it is it 100 lines to 250 lines with Claude's editions, uh more code than I can actually go through it and make sure that every I know what everything is doing. There are no unnecessar unnecessary bits, about bytes.

Jacob Loveless

I mean, everything's an abstraction anyway, like you're not handwriting the stuff in assembler. Um, so like the syntax, I don't think matters as much as people think it does, or the style doesn't matter as much as people think it does. It's can you comprehend this? Like, what is the entropy? Like when you literally look at something, can you comprehend it faster? And by the way, like I'm sure that there are people for whom you know basically reading a novel that kind of walks you through what's happening is more is better for them. But you know, for me, I'll I'll I'll take a poem over a novel anytime.

Stephen Taylor

So Stephen, you got your uh Yeah, Jake, for uh for years, Q was my kind of go-to language for when I when I had uh a license to use it uh for pretty much everything. And I would love to be one of the people you envisage for the future writing applications in Q or K. Um, but for commercial applications, uh I will be writing them from a customer who's gonna say, well, if anything goes wrong, who can I call who has to pick up the phone?

Jacob Loveless

Yeah, I yeah, I think you're asking kind of what is the long-term commercial plan for L? Um and I don't have one yet. So um, you know, I think it's good to put it at a time.

Conor

It's definitely that making a choosing a brand name to keep support because that just I don't know if it's just me, but I can barely make out what Adam is saying. Uh your audio has gotten a little choppy.

Jacob Loveless

But yeah, I I don't know what the long-term commercial application is. I think, you know, Steven, right now is can you run all these workloads? Um and can you run them in order of magnitude faster? Let's let's try to get that first. And then, you know, then we'll deal with the next part next. Um again, I think the good news is right, if if if uh you know this is compatible, this is dropping compatible. So I mean, I think that works both ways. So you can mind have somebody who you know downloads L and builds something, and then is like, you know, I could, you know, maybe if there wasn't an L commercial entity, then you can just be like, oh, well, I you know, I have this code I can call KX, and that's that's great. Um but because it is, you know, like I said, some of the reports from the field are pretty nuts, not just in terms of performance, and I hadn't actually contemplated this, but I feel stupid for not having contemplated it, is storage. So the um, you know, the objects are compressed in memory on disk. I mean, it's all the same format. Um, again, do one thing and just do it everywhere. Um and somebody just basically moved over what is essentially a TAC database to see what the disk storage was. And um, and it turns out it's like eightx less disk, even then the dictionary compressed versions, um, which which I think makes sense, right? Because you know, dates and um timestamps, the base type is a 32-bit and a 64-bit. They're almost always monotonic in the database, so they're always gonna delta really well, and then they're gonna frame a reference really well, and they're gonna um, you know, there's kind of one more trick that I do on the patch. And so you actually do end up like, yeah, like a column of time is gonna be super, super small. Um, if it's a high fidelity, like high frequency set of time. Deltas are gonna be tiny, um, and that's gonna compress down a lot, like a lot, a lot. Dictionary compression just really isn't good for numbers. I I don't know why people love dictionary compression. It's I mean, it's good for text, but it's not not good for numbers. Um yeah. Sorry, Adam. I I I don't know if your audio worked now. I wanted to answer your question, but I couldn't quite make it out.

Adam

I'm sorry. Uh I hope it's better now. Um okay, I just need to reload. Um, but let's see if I remember what it was.

Conor

It was in the middle of the year.

Adam

Right, no, no, I think it's a commercial plan. Because it's sort of sort of a joke, but uh these they're these uh companies that that uh and that sell knockoff products that brand it like uh like real big brands out there, and they for customer support, they just list uh the originals contact information because their products are so identical to to the real expensive thing that that the customer support for uh for the real deal is the same as and as for the cheap stuff that they're selling. Uh it's sort of a joke, of course, because it doesn't it it's not commercially viable in the in the long run to say who do you call for assistance if something's not right oh that your language is behaves identically to into KX product and ask them and look at their documentation and so on. But that's that of course that's a joke. That doesn't work. Uh but essentially that's the situation you're in right now, right?

Jacob Loveless

Well, and I think Steven's point's a good point, right? Even open source code, um, you know, you're not gonna take a piece of open source code, I mean, I guess except for the case of the operating system, and um, you know, go deploy that in a mission critical environment without somebody to call, which is why these kind of open source business models um I I think succeed. Um but but yeah, again, just step one, get it compatible, which we're we're past that point. Um get it, get it fast. Um it's pretty fast. So, you know, I'm sure that the that we're gonna discover more things that we can make faster. I'll give you a great example. So um K, and I don't know if APL has this concept, but K is a concept of a symbol, which is essentially a character string that gets mapped to uh essentially an enumeration, right? So if you have this, is this comes from its use, from its use case, right? So in Wall Street, you know, stocks have tickers, you know, like IBM and whatever. Um you obviously, you know, don't want to you don't want to store a bunch of strings in a table. Like, no, again, terrible like choice. Don't don't do that. Um so what you want to do is you want to, you know, you want to store those as a number, and then you've got a lookup that needs to happen, kind of an enumeration between this this uh array of characters and its numeric representation that sets in the database. And that's great. And that works wonderful. Except you need to have that enumeration stored somewhere. Like if you lose that enumeration, and in K it's called the SIM file. And if you lose that SIM file, like you're smoked. Like there, like you've just lost the map. Like the Torah is now gone. We have no idea what how how things work anymore. Um, and this is this is both a a kind of an operational problem, but it is also actually a performance problem. So in a scenario in which you want to run kind of parallel reads um, you know, across multiple uh partitions, that symbol file needs to effectively be shared, right? They all all those partitions need to be able to decode that symbol file. And so you've got to have a lock on that symbol file. And um, you know, to be completely honest, I didn't do any character codec because, you know, I don't know, I don't just don't use strings a lot. And the community was like, hey, this is great, but is there any way? Basically, they're asking, is there any way you can get rid of the SIM file? And it's like, okay. What we're talking about is we just need a new codec here that will fit this. So again, be practical. It's a workhorse, not a show horse, right? So most financial workloads, the character string is fairly short. Um, so it's, you know, uh generally four or less characters, but certainly eight or less characters most times. Those are holding the ticker, uh kind of the the name of the stock, right? Um, well, you can, I don't know if you guys are familiar with this concept of German strings, but you can just basically take that character, right, turn it into the numeric uh equivalent. And um that has two benefits. One, it's a number, so you know, God likes storing numbers, and two, um, it's like lexographically sortable, right? So sorting sorting that number is the same as sorting the character. Um, so that was the first one. I did that, and it was like, hey, now you have no symphile, every symbol vector is kind of self-describing, subject to you only using small, small character strings. And then um, and if you use a large character string, then underneath the covers, that codec is gonna have to switch to an enumeration, and like you're gonna, you know, now you're back in pain. And then somebody in the community was like, Yeah, but like these options ones, they're just a little bit longer. And I was like, well, then you know, tell them to make them shorter. And um, it was like, well, no, you can't do that. So um that was that was like the last, I don't know, two, three weeks was thinking of kind of what is a codec for for storing a string that still allows you to have those properties. Um, and so actually for a symbol and for a symbol, there is no enumeration anymore. They are all self-described, and each vector is kind of self-composed. Um, and it's like, okay, that's great from an operational standpoint. You don't have to worry about losing a sim file and losing all your data. But boy, does that turn out to be a massive performance improvement, like massive, like more than an order of magnitude, um, because all of these locks on the sim file go away. And because then each, if you have multiple SIMs in a in a in a table, you can now operate them on them independently. And of course, because all the codecs are uh sortable, you don't have to worry about this. You used to like have to go work on the you would go into the enumeration, find the symbols that matter, then go back into the table, and then find the match, and then ah no. So all of that just goes away.

Alexander Underrainer

Yeah, the sim file bloating is going away as well because there's sim files. Like yeah, one one one problem uh with the sim file is like it it you know it makes your data on disk faster, but as soon as you start bloat the sim file, you're losing this performance. And you know, I've been teaching KDB developers and juniors, and often you know, one of the grads, one of their rookie mistakes is like, okay, I'm making a column that's not supposed to be a SIM symbolic column, a SIM, and then you store it to this and you load, you blow up the size of the SIM file, and now suddenly your HTB isn't fast anymore. And then you have to deal with basically recreating your data because there is no easy way to remove something that went into the SIM file. You have to de-numerate everything, re-enumerate it, and save it back down to disk. And that's like a massive pain and a very risky operation. So not having to deal with SIM files, that's pretty cool to think.

Jacob Loveless

Yeah, and again, it's just it's a massive performance unlock. Um, because now you can have each one of these kind of parallel readers operate independently. Um, and you you know, you don't have to worry about a lock. Um, and um, you know, God has a couple of designing principles. He doesn't like characters and he doesn't like locks, and he doesn't like branches, and the more you can get rid of those, the better life is. So yeah.

Conor

Have you noticed other things at least when uh when using uh like uh L versus your experience in the past?

Alexander Underrainer

Um I found it really easy to transition. It's pretty much like I, you know, I came across this two, three weeks ago. Um, and then you know, Jake gave me the binary, installed it, run it, and I thought like I I I have to learn something new or you know, at least read some documentation. But Jake was basically it's pretty much like cube, just start playing around with it, which I did, and I haven't seen much that you know I couldn't do. Um it's it's it's pretty good um from what I've seen so far. And yeah, I like it.

Conor

Do you have any like uh workflows that you notice got way faster, or do you not really have that kind of thing where you're you're running something regularly enough to notice?

Alexander Underrainer

No, I haven't, you know. I've for now I've just done basic stuff. Um I didn't went too crazy on it yet. Um but yeah, I know Jacob runs some some stats and and they look pretty promising. And one of my questions for Jacob was actually like we've we've talked a lot about what you've already done in in terms of you know to squeeze some performance out of it. Do you think you can push it even harder? Like is there do you have are you there yet with L? Are you finished? Do you think it's okay that's the maximum we can you know squeeze out of it? Or or do you have a few more tricks in in your sleeve?

Jacob Loveless

Oh no, there's definitely more to do. There's always gonna be more to do. I think um I think I'm out of ideas for now. So that's why it's like you want more people to have this, because you want to, you know, I'm out of ideas. So let's let's see if anybody else has got some new ideas. But I think um I actually think the fusion uh fuse.c where it actually goes and changes the bytecode. Um one of the things I want to do, and I just haven't figured out how to, is expose that up so that a developer can essentially write new fusion rules in the interpreter and save them down. Um because that's that's where there's just a lot of institutional knowledge that it gives you just huge performance wins. Like, I mean, the classic example is like Connor said, the the fuse multiply at, right? Um let's take this set of operators and let's just move it into a dot. But you know, there's a lot more of them, like working with matrices and you know, working with them in arrays and indexing into the matrices in in in kind of a straight linear fashion rather than the matrix. Um, I don't know. As I come into more workloads, I'm sure there'll be more opportunities to make things better. But yeah, I'm kind of out of ideas of how to make it faster. Um so and really it's like where where if anywhere is it slow, right? So if it's so for example, I didn't do like the uh string operations, like you know, again, strings, I just don't use them. So um, and then somebody in the community came in and they were like, Man, this string search and replace is really slow. I was like, Oh, okay, let's go back and fix that. So um went and fixed that. Um and uh, you know, stuff like that.

Conor

Speaking of the the this is a good time to ask one of the two questions, or maybe both, but uh one of them was relevant to the the patterns that you uh mentioned. Um so the question is all of those fusion patterns and compressed representations uh must lead to a lot of combinations. Um, do you have special code for even uh, and I think it's EG, for example, uh arithmetic progression vector plus a number plus frame of reference vector.

Jacob Loveless

Um, that's a good question. Um no, because all the verbs have the compression operations built in, it really is just purely on the function itself. You do you actually don't um there isn't actually any way to in a fuse operator to say do this if that is compressed with this codec, do this if it's compressed with that codec. Um, but again, you don't really have to worry about that. Um, because all as long as you get all the verbs and adverbs working compute on compressed and closed form, that's really just an implementation detail. Um where fusion really matters is again kind of institutional knowledge. I see this, it's it's better to do that. Um and that really is just like you know, institutional knowledge.

Conor

Um or tricks. All right, so we'll go to the second question too, and then we'll go to Steven. Uh so the first the first question was from Asher. I forgot to mention uh Asher's uh I believe a dial dialogue employee. So both of these are APLers. Uh the second one's from Max. Uh is scan, this is rather uh specific, is scan linear or quadratic in L? Uh because across languages, uh sometimes it's quadratic. It has the K does, right?

Jacob Loveless

Is scan linear or quadratic?

Adam

What he means to say it is when you've got uh you've got a a verb followed by backslash, uh you're taking the partial sums, whatever to uh run it and running some. Do you start over every time going from the left or do you reuse the previous uh result? Because the the point is that uh a verb, b verb c uh by apl and k grammar, you need to start to compute from the right to left. And therefore, there's also the the idea that if you do a reduction, uh fold, insert, whatever you want to call it, uh then that's equivalent to just having all the elements spread out with a verb between them, so you need to go from right to left. Okay, that's all fine. Um, although we spoke about not worrying about uh just commutativity of uh and of mathematical functions. But when you get the scan and you create a cumulative sum, then you cannot do a single pass computation because you really need to go to the the last element of the of the running sum has to be the last element plus the second to last element plus the third last element and so on. But the second to last element, you have to start with the second to last element and go to the left. And if you're strict about this, if you're strict about the order of operations and strict that uh each partial sum must match the equivalent sum of that, and you're strict that the sum has to run in the uh element that element, so no CMD, then you end up with uh a terrible performance because you have to stud over for every element in the scan.

Jacob Loveless

Right. Okay, so this is gonna be a long answer. So the um, but this is a place where fusion plays.

Adam

So um but hold on, before you answer that, I think I can sort of sidestep the question. There are two things played in. If I remember right, case definition of uh of a scan is strictly left to right. You just keep adding one more element. I mean, that's that's the first thing. So the question doesn't come in. Second thing that sidestep the question is you don't care about the order of uh of application of commutative functions. So this whole thing is only only comes in into that because of being strict about it. So it would seem to me that there's nothing even to answer here.

Jacob Loveless

Yeah, obviously not. There's nothing really I I think beautiful or magical about this, but I will say this that the fuse there in fuse.c, they're obviously operating. So prefix sums is something you use all the time, right? So um that actually calls very specific C code for that problem. Um that allows not only to use SIM, and actually there's a great write-up on that on parallel prefix sums on um algorithm algorithmica, I think. But um, but that one specifically, the sums, prods, mins, maxes, um, those all have custom C implementations because they are used uh specifically and they're SIMD implemented and parallel implemented. Um, and they're they're they're fairly bespoke. But if you were to do like F, you know, create a function F and do like um F scan, um, that will just operate like A, where it just goes, just kind of runs through it as fast as it can from left to right.

Conor

All right, you waited patiently, uh Stephen. Now over to you.

Stephen Taylor

Yeah, I want to comment a bit on the implications of what we've been hearing over the last hour. Uh Romantic Alex Unterreiter and romantic Stephen Taylor called a meeting to uh work on shared community uh queue libraries, and cold-eyed KDB dev said there's no use case for those, and we're not coming. So we wound up canceling the meeting and feeling very sad and having a little weep. Um, and then Jake released his L interpreter. And now, I mean, I can't remember who I heard call the use this term first, um, but the language has got jailbroken. The first time we've been we've got um Q that you can use um in uh uh uh uh a commercially performant uh interpreter and can use it anywhere, or at any rate, the prospect of it. And um this seems to be the time for this because um there are other there are other projects working on the same thing. Jake's the first to come forward with a hundred percent coverage of the language. Uh I think Peach Q is reporting 43% coverage, peachq.org. Uh and uh John Estrada with his Courtsey uh interpreter uh reckons he's at about 80%. So this is a completely new landscape for the language. It's broken out, it's jailbroken, and there's clearly a need for some kind of community meeting to work out what community resources could be shared between them and so forth. What we need to do, and that will take some time to plan and organize. Meanwhile, at um Milden Hall in September, there's um the original failed meeting is coming back to life in some form, and neither Alex nor I quite know what's happening there. But John Estrada um will be there with Kortzi. Uh his collaborator Rob Hodgkinson will be there from Australia. We're expecting FinTan from States with Shack T. Uh, and uh we hear Dave Thomas is coming over to talk about uh what needs to be done for the community. So we don't even have an agenda for this, and we don't yet know who who's coming or who needs to be there. Um but our celebrated chef is back. And um so so I'm better uh I'm basically putting this out there that if you if you listening are someone who wants to be in on the very um the the very ground zero of what looks like a first actual community for K and Q, um get in touch with Alex or with me.

Jacob Loveless

Yeah, and I gotta say, man, as someone who grew up in this community, you know, when I came to New York, I didn't know anybody. I got this job in New York at this, you know, at this shop, this Kennerford show. And um I literally reached out to the K community and was like, I'm here. Is anybody else here? And like the first beer I had, the first dinner I had, you know, the first apartment I went over to, um, you know, the first group of friends that I ever made was, you know, KMQ programmers. And like, um, you know, what's a kooky, quirky community? And I I miss I've been gone for a long time, so it's nice to come back and be reminded, like, oh, there's a whole city under here. Like this Discord server was like four people, and then it was like 40 people in like a weekend. Like, um, and yeah, I think there's you know, I used to make jokes that when I was people, people uh people like, what is your preferred language? And I'm like, oh, I always prefer programming in K. And they're like, What is K? And I'm like, it's there's dozens of us, like dozens. Um, but that's not true. Like, there's actually hundreds of us, and and you know, maybe thousands of us soon. Uh, we just need to make sure people have access to it. Um, have access to it, can play with it, and like not play with it in just educational ways. Like, the only way you actually I I say this all the time: the only way I can actually learn something is to use it in anger. Um, like it needs to be put in these situations where you have to make it work because something depends on it. Using things in anger is how how you get good at things. So um yeah, man, go go download L and like go use her in anger. And if something's wrong or slow or you know, just send a note. Well, like I'll I'll take a look at it. We'll get it fixed. Like symbol file took two weeks. So, and you know, how hard could the rest of it?

Conor

So the the downloads available obviously at the lv1.uhsh link. What's the best way if you run into issues or you just want to leave feedback? You you mentioned a Discord, but that sounded like a smaller private thing. Is there a a go-to space, GitHub issues or Twitter or something? What's the best way?

Jacob Loveless

There's there's actually when you go to uh when you go to that website, when you go to lv1.sh, there's a mailing list and you can join the mailing list, um, which is how it used to work in the old in the olden days. Um I like the mailing list. I I I mean the Discord's fun, but um I like the mailing list because it allows, you know, you can work a little more asynchronously. Um and Randy just, I think last night got a forum up so that you can go and you know search old uh see kind of the mailing list archives and be able to search it. So um if you want to get in touch with with me, that's certainly the best way. Just send, you know, join the mailing list and then send um send a message to the group and then I'll get it.

Alexander Underrainer

One one one thing I want to add, and that comes from you know the early days when I started to learn Q. Um, the original mailing list, everyone could see who sent an email to the mailing list. Now it was, you know, with some veterans who have been doing Q for a long time, and it always felt intimidating to ask a question out in the wild, and then you know, the imposter syndrome, wondering whether everyone is gonna laugh about you and think you're stupid. So Jake actually made the mailing list anonymous. So whenever you send uh email to it, unless you have a signature in your Gmail address like I do, no one will actually see who sent it. So um that's a good way to ask your question without worrying whether you're gonna be exposed for asking something stupid, even though there are no stupid questions, only the ones not asked. And then for all the listeners who are not coming from a Q background or haven't learned the syntax yet, um, go check out my blogconq.tech where you can actually learn the language and the syntax. And I think I did a pretty good job in explaining it in a very easy, comprehensible way. Um, if anyone wants to chip in, Jacob, Steven, um, you can give your opinion about it.

Adam

I just I just downloaded it and it runs. I was about to ask, wait, what if I'm on Windows?

Jacob Loveless

So you should think about your life choices, Adam.

Adam

Like, that's like that's you've you've made some bad turns in life if you've ended up with well, Windows now has such a thing called as uh WSL that can run Linux things, so that's what I'm doing, and it works just does that work? Yeah, it works fine.

Jacob Loveless

There you go. New platform supported.

Adam

Yeah, so that's fine. Um now you know. Um, but uh you one thing you might want to do is make it available to run in the browser.

Jacob Loveless

if you can if you can target web assembly or something like that with a C to WebAssembly thing or I I I don't think that does WebAssembly have SIMD built in it it is deeply SIMD specific.

Adam

I know there are there are things out there that are able to compile C code. I don't know what happens if it has deep simd things I would imagine that it would work but I don't know. I don't know anything about these things. But it would be something that's very nice for a language like a small uh existing audience is to have something you can try right away in your browser. So by whatever means necessary like even if you need to run some kind of virtual machine thing that's um in the browser that can then run it that makes it very slow but just that people can get a feel for it that might be a nice thing. But then I then I found an interesting quirk uh of the L language we can call it an inconsistency but it sort of has to be the way it is it's just funny I think I wanted to mention this. That is I happen to know I don't really know KO Q but I happen to know that in that in Q if you apply uh a a string a character vector to the character uh k then it gets evaluated as k code so here's the fun thing if the language name is L uh it this still works it is implemented I just tried it yeah but that means the language sort of claims to to to evaluate K code I guess it does it does evaluate K code it does you can actually you can just hit the backlash and you actually drop into the game to I that that's the first thing I do I don't I don't need no Q. Give me K.

Jacob Loveless

Yeah Q is Q is uh complicated um K is a lot simpler. The um yeah the only thing that is still gated which I'll ungate soon um is the is the offload the GPU offload. Again it's just transparent. So um I'll ungate that on the Mac first because the hardware is consistent and it has unified memory but yeah that's GPU go burr is really good for like it's really good for sort at stupid large amounts. Actually I mean you have to have really really really big arrays for that thing to actually start to kick in but when it does it's pretty it's pretty amazing. So we've got a comment in the chat from uh Madeline who's mentioning that uh WASM has had simd for a while so I mean there it could uh be possible um there's there's maybe uh there's a there's a project there maybe I'm not um I'm not I don't really do uh web development but I'll I Randy Lebeau who built you know like the forum and the anonymous email list and all that stuff I'll ask him he if anybody could do it he could do it so see what we can do.

Adam

Max meme god says says that yeah array box please well well I mean I once it runs in in wasm then you should be able to get to run it on the Raybux as well.

Conor

Once someone implements the Wasm it should be pretty straightforward um but uh one last thing too because I know Steven you mentioned uh for people to get in touch is there uh uh what's the best people what's the best way if people are interested in um attending the upcoming uh event um is it to reach out to you is there uh an a another mailing list um just so that I'm I'm sure of the folks that are listening there's gonna be a handful of folks that are interested so I want to make sure I'm pointing them in the right direction. As we record this it's not there but on Iversoncollege.com um there'll be a notice about what's happening with the meeting or at any rate what we know about it uh and an invitation to reach out to anyone who thinks that they like to be at the potential ground zero of a new or what should we call ourselves Alex communards I like that all right so I mean uh if if you uh if you're listening now you can check uh Iversoncollege.com if it's not there yet uh we will uh Steven will let us know uh Adam and myself and when it is live probably uh by the next time we're releasing one of these array casts uh we'll be sure to announce it and point people in that direction um and with that I will say uh thank you so much uh to all of uh Jacob Alex and Steven this has been awesome I've learned a ton I mean it's super exciting I also I didn't realize that there are it's not just L out there I learned about Peach Q and you mentioned a couple other ones uh we'll be sure to link all of the different flavors of these uh I guess Q implementations that are out there and uh will be very exciting if if you are having uh a meeting and uh folks are getting together um because yeah it's it kind of feels like uh I don't know maybe Renaissance is a bit generous but uh it it feels like there's a a shift in the Q wins and uh the same way that there's you know a number of APL implementations, whether they're hobby projects or more serious um that yeah this is uh as an enthusiast of different array languages it's very exciting to to see this kind of development happening. So um yeah thank you so much for for coming on and we'll be sure to link to all the different uh things that we uh mentioned in both the YouTube description and the show notes so check those and uh with that we will say happy array programming uh