Welcome to episode 130 of Arraycast. I am your host, Connor. We're back from a unscheduled or quasi-scheduled. I guess I could have anticipated that this was coming. Two-month break. Last time we recorded was at the beginning of August. It's 2026, for those of you that are listening to this live on YouTube or recently on the podcast platforms. And it's now October, and we have back with us a very exciting guest. The last time she was on was, I think, episode 77 of a Raycast, but was on Tacit Talk two times in between. Those links aren't in the description or the show notes yet, but they will be after the fact. And I guess we'll have her introduce herself at the tail end, because we're doing this live now, so we do the introductions a bit different. We'll do uh brief introductions. We'll start with Adam, then go to Max, and then I guess we'll we'll finish with uh Kai, who's back to talk about uh a new release of Weewa, Weewa 0.19. But first we'll go to Adam and then to Max.
AdamRight. So I'm Adam Brzevsky. I have been doing APL all my life, most of my life. And I am currently head of language design at Dialogue Limited.
SPEAKER_00Okay. So yeah, uh next year is uh my array test uh debut. And uh yeah, I was previously on Tested Talk, and uh I'm interested in uh notation that uh help us think in general, whether it's a tooling or uh written or uh computerized. I'm also a proud sponsor of what we want.
ConorThere we go. We didn't know that. And I'm doing I'm doing a bad job of moderating. I should have mentioned, and uh the uh astute listenerslash viewer will know that uh last episode, I believe it was episode 129, we had our first guest panelist, which we kind of started from a couple episodes before that. We had said, you know, long term we're looking to grow the panel, and in the short term, we were uh we had some uh a request for uh people that were interested in being guest panelists. And I believe Madeline, famously of Tiny Apple, was our first guest panelist, and Max is now our our second guest panelist. We've got our our guest Kai to talk about Wewa, and Max is here as well. We'll have lots of questions. So now that my moderator job is done, we'll throw it back over to Kai. Uh I I'm sure everyone knows who you are, but uh just briefly introduce yourself and then I think we'll have a couple announcements and we'll start talking about Wea.
SPEAKER_03Um yeah, I'm Kai, and I'm the creator of Weewa. That's it.
ConorThat's it. Poof. Like showing us how it should all be done. I guess we're not all creators of things though, so it can't be that emphatic. Uh, you know, I don't I'm not able to say that. I can just say I host some. Uh perfect. So uh I honestly I forget who has all the announcements. I I know Max has at least one, and uh Adam has zero or one, but uh so we'll go with Max and then over to Adam if he has Okay, so uh my announcement is for uh people local to Toronto.
SPEAKER_00Uh that's uh based in Toronto, and uh there's uh a real programming language event, I suppose, uh hosted by uh Data Intellect. Uh it's about uh the Q programming language, which uh was derived on APL. It's uh happening uh this uh uh first day, uh 2 to 5 p.m. uh near downtown Toronto.
ConorLink will be in the show notes. I think you have to register in advance, and this is definitely the kind of thing pre-parenthood I would go to. Now I will not have the time to make it, but uh I will be there in spirit. So yeah, link in the show notes if you're local to Toronto this Thursday. So I guess you will have had to listen to this either Monday, Tuesday, or Wednesday. Link will be in the show notes. And Adam, I can't recall. Did you have zero or one announcements? I know at one point you had.
AdamYeah, or or maybe two or three. All right, we go. Um we're gonna start off with uh April Germany's uh autumn or fall uh meetup, uh which is going to be in Solingen, Germany. Uh, and that is happening on the 5th and 6th of November. There isn't any program up yet on the website, but uh should be coming very soon. Um you can register there as well. There's probably going to be some mixed German and English content. Um and then we I think we touched on it briefly when we in the last episode, but now it has been properly announced, the winners of the APL Forge, which includes Connor. So congratulations to Connor. Which leads me to the third announcement, which is congratulations to Connor. Because you just sort of hinted at it, Connor, but you haven't said why this whole break was there, but Connor became a father.
ConorI can never tell uh in the cinematic universe that is all the podcasts that I host, uh where I've announced it or not. But yes, there's the for the congratulations and uh the kid was on the way, uh, is what I announced on the previous podcasts. Um and now the baby's which is uh partially why we're delayed. A raycast is still here, it hasn't disappeared. The podcast well, we plan to still do every two weeks, but there might be a missed episode because as Adam knows, take time a priority all and is also my view. I should I should air. Um anyways, was that the final thing or was there one more?
AdamYeah, that's I think that's that's it. Yeah.
ConorAlright, so that is the announcements and the introductions out of the way. So I have on the side, I mean I'm not sharing it, but so on episode 77, that was uh Kai, your first interview on a ray cast, and then it doesn't say it in the title, but if I recall, it we did this exercise on the second Tacit Talk episode where we tried to figure out what edition of Weewa was out, but we'll say it was like dot oh nine or dot 10 back then, and then I I made the uh the fix of an episode 19 of Tacit Talk. We were talking about dot 15, and now I think it was at the tail end of August.19 officially released, and now dot 20 is in beta. Uh so I'll throw it over to you. Um, tell us what's new ever since I guess uh dot 15 if you want, but maybe focus on the dot 19 stuff and then we'll go from there because I'm sure that there's a I've seen I've seen the the change laws and I know that there's uh new primitives, there's deprecated primitives, there's new features. Uh so lots to talk about.
SPEAKER_03I mean, if you're going back all the way to what 0.15 you said, it would be that was over a year ago.
ConorSo it was over a year ago, yes. February 21st was uh of 2025 was the last time. So it's about a a year and a half since the last time you've been on a podcast, or at least a raycast or Tassatalk. I don't know if you've been uh hitting the other podcast uh what do you call it, Markets.
SPEAKER_03Um I I think because we this is like titled 0.19 right. I'll start with that and we'll see where we go from there.
SPEAKER_04Perfect.
SPEAKER_03Um, so most of the big features in 0.19 are remain experimental. Um, I can go over them in order of how likely they are to be not experimental in the future.
ConorOkay.
SPEAKER_03Um, so let me share here.
ConorAnd this is the beauty. If you're listening to this on the podcast platforms, I'll talk about it. This is live on uh YouTube. I mean, it's great to hear it in the podcast, but also too, the visuals are fantastic. We got syntax highlighting, we got WeWAPAD here. Yes, feel free to check out the YouTube maps. I can see it great.
SPEAKER_03Yeah, cool. All right, so uh increasingly, and if we go further back in the change logs, we'll see this. Um, we will have more and more into um sub the subscript syntax, which is where you attach a little number to something. Um, not just numbers, but other symbols too. In my mind, this is kind of analogous to um AP or APL's um like bracket syntax, in that what it does for each primitive is kind of ad hoc. Um it's it usually makes sense, but like you can't necessarily know exactly what it's gonna do. It's not it's not a uniform um transformation of that primitive. Um but one thing I want we wanted to add was the ability for you to define your own behavior for these. Um, just as an example for those who haven't don't know them. Example, like um, what's the example of a subscript? If I do something like uh give myself a little array here, um and then if I want like the first item, right? That just gives me the first one. But maybe I want the first two or the first last, no, maybe that one doesn't work, or like the last three. Um, and it changes the behavior of this thing. The same thing for like um rows. Like if I have a um a big array of a bunch of numbers, uh two, three, four, five. Um this is kind of like for this, it's like a rank operator, right? Where you do like rows, uh, I don't know, two box, like box every rank, two array, box every rank, uh, one array, box every rank, three array, right? Um, so we want it to be we want it to be possible to to find these for your own. Because if I combine some function, uh maybe I want to what does F like sub five do or something? Um so well, uh this feature is custom subscription.
AdamBefore you continue, I I'd like to draw just the parallel because it might not be obvious to everybody what the what's happening here, but I think it's it's apt to draw the parallel to especially to BQN, actually. You said you it's similar to the bracket access in um, or for example, in bracket access in in APL. But actually, we noticed that in APL there's there's some pairs of operators, monetic operators and dadic operators that pair up nicely, where we have the the each operator and the depth operator. Depth operator is a more general form of uh of the each operator. And so too, you can go the other way. We have the general rank operator, but then there's an another operator which is unmajor cells operator. And you could also say that that first and uh and take are sort of variations of each other. So essentially, here is you're you're sort of reinventing that duality between monetic dadic functions like first and take, notably not in dialogue APL by default, but in APL2, the the uh up arrow means first and means take, right?
SPEAKER_03I I would say in some ways, so if I go back to that example real quick um with all the numbers, uh there is a difference, right? If I do take two here, it gives me one and two, whereas if I do it gives me the array one, two. But if I do first two, it gives me two different results out, um, which is different.
AdamOh, I see. Okay, so there's a difference there, yeah. Okay, it's sort of still sort of the same idea of having the same primitive do two related things. Um but okay, I get it. But and but with the with the operators like you did when the depth one, right? On rows, but then you say on subarrays of rank, that is the same idea, right?
SPEAKER_03Yes, yes, it is. Um and I should point out that like uh a lot of the behaviors we assign to not all of them, a lot of the behaviors we assign to subscripts are numbers that should be known at like compile time. Um like for example, you can put any number after the take, basically, and it'll it can be any always produces the same number of arguments.
AdamWhereas for the same thing. But you can't compute the subscripts, right? They have to be fixed.
SPEAKER_03Yeah, they do. Um you can like do macros and stuff, but it'll still run at compile time. Um the this first here will always produce two outputs, but it has to know how many outputs a thing is going to produce at compile time. So you couldn't make this necessarily a um a normal function. It would have to, it has to be uh compile penal. That's not true for all of them. So I can just take that too, take two, if I can make that a subscript. So some things just have a subscript that means bind this more tightly together so I don't have to put a parentheses around it or something.
AdamUm so take actually does do this. So essentially you can do it.
SPEAKER_03Same thing as most of like the uh arithmetics, arithmetic things, right? Um it's that's what it's gonna do.
AdamUm it's sort of interesting you're breaking the mold because we is is essentially a fourth, right? Um in some ways, yeah. But then but now we're introducing well, not quite infix notation because it's still prefix, but it's sort of I mean the difference is you're writing it like this, right?
SPEAKER_03It's still yeah, yeah. The main the main difference between like plus subscript plus subscript one and plus one is that um whether you need parentheses if you're trying to do it as part of like a larger, like in in a modifier or something.
AdamYeah, it never it never ends up on the stack, right?
SPEAKER_03The one e well it does. Well, it compiles to the same thing, right? Um it's it's more of a syntactic thing, right? So if I wanted to do say like on plus one, if I separate these, the meaning becomes different.
ConorI've always loved that about about WiWa. That it uh it like unitizes it into a single, it's not actually a single glyph, but you can treat it that way. And it's one of the things that irritates me about other array languages, is like I've always thought about like a hypothetical array language where instead of plus slash or slash plus, like I think actually someone in an array cast or tacit talk mentioned it once uh like kanji, like Korean, like where you build up or like Chinese, you build up a symbol out of radicals, like instead of a slash, you like you circle the plus or the binary operator. So it's always a unit. And because there's so many examples, especially when you start doing tacitly, which I guess is always the case for for Weewa, and you end up having to parenthesize things in order to pass them around with combinators correctly. It's it's a very nice like feature. When you when you first introduced this, I was like, oh my god, this is beautiful. When you want it, it makes so so beautiful.
SPEAKER_03I've had the offhand idea to lean into it more with like the um the combine, you know, there's like the combining Unicode characters, uh, but that gets real complicated for like parsing and display real quick.
ConorOh, like I got I thought about it too, and I've like you basically would have to build your own kind of like website editor where that's the only place you use it, because like how are you gonna do that in the command line?
SPEAKER_03You basically have to usually when you're writing string manipulation stuff, you're not thinking about that. And so anytime you're working with like string manipulation manipulation code that works on source code, you would have to like take that into account, and you'd have to parse everything as Unicode graphing and stuff, and it'd be a lot. Um so the the whole point of this, right? That's there's subscripts. Um, these custom subscripts, you essentially write the name of a function, I'll call mine F, and you give it a subscript N, and then you can say that something. So I could if I just wanted to use that N in here, I could just do this, right? I could you do uh N like this. And what this will do is now I can call F with like F sub one or F sub two or three. Um and that we'll just put it in there. Alternatively, I could do something like this, um where uh I can use it as the subscript for some other modifier.
AdamUm and so it I can also do it is really just an extra argument in this case, much like say GNU APL allows you to do with the square brackets.
SPEAKER_03It is an extra argument, although it can take sorts of things that you couldn't take as normal arguments. Like you can't take this N as a normal argument, or you couldn't, if I wanted to do like say uh both sub N right here, right?
AdamUh, because it has to happen at the compile time. So because you're doing it at the compile time, you're able to put it in in the subscripts that need to be there available at compile time. I see. Yes, exactly.
SPEAKER_03Uh that's the whole feature, basically. Um, it's just nice to be able to do that for your own stuff because subscripts have become so ubiquitous in the language. Um if you're trying to write your own APIs and stuff, it's cool to be able to use them.
SPEAKER_00Can you do computations in subscripts like uh OnePlus One?
SPEAKER_03Not currently, although I've thought about it. Um, but no, not right now.
SPEAKER_00It's uh do you always want it hard-coded?
SPEAKER_03Sorry, what'd you say?
SPEAKER_00Yeah, I'm wondering, you know, it's uh you can do computations, but uh what uh would be uh the use case for that?
SPEAKER_03I mean, if you want something to be offset a rank or by one rank or like up or down a rank, I think that'd be the main use case, or up or down like an parity, like this both symbol is. Um that'd be the main one. You can still currently do that stuff if you really want to via like macros. Um it won't actually be a subscript, but um that would it would be cool to have that, yeah.
AdamI I'm wondering if it isn't slightly dangerous. Yeah, you can use this as a sort of extra argument, but it's compile time. But if people start using it for things that actually could be dynamic, that lessens the ability to call those, call that code, because the only way to call it is by with fixed values. It does.
SPEAKER_03It does, yeah. I mean, ideally for something like this. So let's say I had um, let's say I go back to my other example where it was um just plus, right? Now you probably wouldn't just do plus, you would just write plus your thing, right? But um, if I do something like this, right? Um, I could make a fallback, which is like something like this. Um or I could make my special version that isn't a fallback and it's just the original version, right?
AdamUm, I can write this one like this. They're essentially just parallel names, right? Because it's all static, it's all compile time. That means F and F sub N aren't really related.
SPEAKER_03I mean, no, they're not. Um, I did have a system that made them related, but it got like confusing both for the user and for me, the implementer. Um so yeah, I separate.
SPEAKER_00Yeah, I think the ST of subscripts uh adds uh an extra entity to to functions, right? You have uh one more uh space uh to to put in to put to input uh uh I guess the numbers for now.
AdamYeah, but I find it really interesting that you that that you have the need for this in in we were. I mean, uh yeah, I understand the the syntactic nicety uh shortcut thing, but I thought I I always thought of what this maybe the strongest argument for we were was freeing itself from the Iversonian one or two arguments only. And and here we get back to being sort of static with a bound in syntax.
SPEAKER_03I suppose. Um in a way. I mean this these will like if I want if I go back to that example where we do um both, right? Um you could notice it does change color. Um it does change color depending on what the subscript is because it knows that its area changes as you change what the subscript is, right? Um that's because this is do this box on this many arguments. Um and so it knows that you're changing that area. Um although I guess you're talking about array in a different sense, aren't you?
AdamYeah, it's just uh the the number of like distinct inputs that they are there because we can distinguish between an array of n elements and uh copying n things off the stack, whereas the traditional way of solving this problem in in other senior languages is just put things into an array, but you can't really you cannot distinguish, you can't write a function that distinguishes between give being given a list of many arguments and just being given a single argument, which is a list, unless you start requiring the user to add an enclosure, a boxing. So sure.
SPEAKER_03I mean that there's ways to like take a list, uh take an array and use its rows as arguments um to a function pretty easily. But yeah, um cool. That's the first one. This is probably gonna get stabilized, it's currently experimental, um, but it's it's pretty simple features, so I don't think I think it's pretty good. Um anything else you guys want to ask about that before I go to the next one?
AdamSo what happens other uh so you can have gaps, right? Because you can you can define F sub n here, you can you can define also with a specific number what it does.
SPEAKER_03Yeah, if I wanted to like yeah, you could. Um you could do like F2 equals um I don't know, five, sure.
AdamSo then with it it put it prefers the most specific form and then falls back to the general form, or uh I think hold on.
SPEAKER_03Ah, if yes, that is true. If you define them in the correct order. Oh no, actually, just always, just always.
AdamYeah, yeah, that's that's worth noting. But it's it wait, but I mean that's it's sort of neat, right? It it it I think this might grow into some something more, or there might be use cases that we don't even think of today where you can use you you can you can like lean on this and say, Yeah, I want it defined for these cases as you could potentially you could have it even sort of recursive, right? Where the general case is defined in terms of the of some specific case.
SPEAKER_03Yeah, for sure, for sure. I can I can probably come here and hopefully this works. If I do like F3, um yeah, and then this is like well, F2 is F32423, and then I'll put like I here, and then F2 is this specific case, whereas F4 still exists here, right? So yeah, you can do all these like reflecting.
AdamYou should be able to implement Fibonacci that's at compile time or something.
SPEAKER_03I suppose.
AdamOh, all of a sudden the compiler becomes too incomplete. That's great.
SPEAKER_03I mean, it already is. There's compile time. You can run code at compile time. You have been able to for a while now.
AdamOkay. Um sorry, I mean I'm distracting you from the next things. It's fine. But this is pretty quick.
SPEAKER_03I can talk more about the broader features that have been released in the past few versions, but um the next one for 0.19 is the beginnings at least of a type system. Um the type system is is and probably will always be best effort um in that normal Wii with code is not strictly, not all the types can strictly be known at compile time. Um the simplest example is if I do um reshape random ten five, right? This will give me a random number of tens. The shape of this thing is not known until runtime. Um so you can't now, or if I do like um something like even like this, right? Uh Now it's really not known. It can be any size, right? Um, and so a type any type system for Wewa is always going to be do its best. Um, so there's two components of this type system. The first one is the first, but validate this modifier we call validate. Um and validate takes a an array representing the type, which I call a type spec or type specification, and the thing you are validating. And if the type matches, if the value matches the type you specify, um it just returns the value unchanged. And if it doesn't, it doesn't error. Um so this has both a runtime and a compile time component. Um, but just as an example, uh the way you might specify uh a type. So if I wanted to say, um, for example, my array must be an array of real numbers, um, I'll say num and this is gonna format to this cliff, and then some numbers here. And if I try to put characters there instead, it doesn't work. Expected array of real numbers, but found an array of uh, well, in this case it's add two characters. Um another thing you can do is shape. So if I want to say you must have shape two, three, and then I make a shape two, three object, it works. Um but if I make a shape say three, three object, it says no, expected two, three, but it got three, three. If I want to specify both, I write um num2 three, and then this it works. Um this is specifically, it makes this this uh type tag is a box array, a box list of this type tag, which is itself just a character, um, and then the numbers two and three, which are the shape. And if I try to do this, it doesn't work. And if I try to like make it um a character thing, it it says it expected the different type. Um you can also do like wildcard axes, so um this net can now be any first axis. You can also specify that um the shape you have is just a prefix requirement. Um so now if I do expect it, oh let me turn this on. Um now if I do this, um a five-three array works, a five-three, two array works, a five three, one five array works, but a five-four something, something, something does not, right? And it even says, like, we expected this thing to start with wildcard three, but it starts with five, four, right? Um, so you can do some cool stuff with this. The other piece of this system is so you can you can use this, it would run completely at runtime if you use just this. The other thing we have though is um what I call type signature comments. Um so if I make a function, let's say I make a function and it's just gonna be plus right now. I put a comment and then a question mark, and then the formatter is gonna say, Oh, this takes a real number, array of some shape of real numbers, uh, and another array of some shape of real numbers, and then it'll give me back that. Now, if I say no, no, no, it doesn't take that, it takes the first argument to actually be um characters, then it um says, Oh, then this one needs to be characters, this one needs to be integers, and it gives you back characters. Or if I say something like, oh, and reshape at the end, it says, Oh, now it's two, at least a two long array of characters. Um, this is implemented as an entire essentially interpreter that works on types instead of values, um, with like shapes and scalar types that it's doing, running the functions on. Um not everything is implemented, obviously, but a good amount of stuff is. Um and so you can also if I if I try to use this in a way that wouldn't make sense, like for example, if um if I say, you know what, both uh validate that it's a character, it says, okay, it takes two characters, it gives you back two characters. And then if I say plus here, it tells me at compile time, like you can't do this. You can't add characters together, it doesn't work. Um so it can catch stuff for you, like type errors for you um at compile time, which is cool. Currently, this is just a warning. This could could maybe should be an error, but I'm not a hundred percent confident in it quite yet. Um so right now it's just a warning. Um yeah.
ConorHow did these um this is very, very cool. Uh how do you like because right now it kind of looks like you're building like type functions that kind of assert stuff on the uh arguments. If you're solving or or you're writing like a function, how do you how do you idiomatically uh use this? Like it is there some kind of thing that like checks and then kind of throws away that check if it doesn't raise an error and then you have the rest of the function that's computing something? Or um like because I'm I'm thinking of like procedural non-array languages where a lot of these type checks are specified kind of like in the the signature of the function or using some you know Rust or C template y you know trait stuff. Like how how is it supposed to be used?
SPEAKER_03And so the idea here is that if you really care, because because I think one of the big benefits of not just array languages, but like dynamic languages in general, is that you don't have to care most of the time. Um, but I have seen people write Wii code before I implemented this feature where they basically implemented something like this themselves because they wanted to make sure that like you're passing all the correct things to your functions, um, just uh for sanity and stuff, both for the developer and the user. Um and so you are meant to interface with this. One, this is for you, the reader. This you if you change this, changes to it will be overwritten. This is for you reading the inputs and the outputs. Um, this is something that gets past what certain there's languages like OCaml and stuff, which have a very powerful type system which can fully figure out tons of types without you specifying a single thing. Um, but then you get these like type errors that percolate up to someplace that is unrelated, right, through a big called stack. Um whereas this, um, it tells you right there, this you don't have to write the signature itself. Um, and it just fills it up for you based on what it's been able to infer based on the inputs. If you really want to specify your inputs, you are meant to do it by using validate. Um, you can get some results even without using the code. So if I say F is take two, um, it doesn't know what you're inputting, but it does know whatever you're outputting, it's gonna be two by something, right? Um, because take will err if there's not enough items. So it has to be two by something by the time this function returns, right?
ConorThat's so neat. This is very like Haskell. Um, you know, there's some feature, I can't remember what it's called, but like if you leave out the type signature, you hit some button, it'll automatically like populate the the most generic, uh, or is it the most generic or the most uh I haven't used, I'm not the Haskell. We need Tiny Apple uh Madeline here, but it'll fill in the type signature, you know, you don't have to do anything.
SPEAKER_03Yeah. So and there's cool stuff like if I do like um a transposter, um, now the two's at the end. And then I can also do like a reshape three, and now it's like three and then some number of axes and then a two, no matter what you put in. Um so it's relatively, I mean, there's limitations to this, it's not like a perfect representation of all possible things it could be. Um, but I think it's pretty cool.
SPEAKER_00Do you have a type for a subscript script of functions?
SPEAKER_03Yeah, it doesn't have types for so subscript functions are implemented at custom subscript functions are implemented as macros, and it doesn't have you can't do this on any macros. Um just because their entire signature is instantiated at the call call site, not at runtime, but at the call site, uh, rather than the definition. And so this could vary wildly depending on what your um even like the number of arguments it puts here could vary wildly. And it doesn't know all the things you might be putting into the the macro.
SPEAKER_00Uh what about uh combinators like uh both?
SPEAKER_03No, any anything that's not a function, it won't work on.
SPEAKER_00Oh, okay. So yeah. So it's always the derived functions.
AdamYeah. You could unroll combinators, right? To render them as normal functions and then do do the analysis.
SPEAKER_03At least some um you can't. Well, I mean, I can okay, I can use a combinator in here. Like if I do uh like um on V shape, and then I do like, I don't know, validate T3. Um like it it you can put combinators in the thing. They're that they're handled. Um, but you can't like if I just make some modifier that's like this and I say on this, um I it doesn't it can't it can't work on that. It doesn't know. It should honestly it should give you a warning here. It's not right now though, um, because it can't process this properly yet.
SPEAKER_00Yeah, I think if this gets hairy when you try to address these like uh higher order uh constructs.
SPEAKER_03Yeah, for sure. Um that's easier though. Um and so also it can even if you don't put these, I can I believe I share if I put this up here. Um and let's say I do something like my array, it requires a let's say um uh length of at least it takes in a length of five, right? Now if I put this here, it says okay, length of five. But if I don't even put that there and I just put um say let's say like take ten, it can tell like oh wait, wait, wait, wait. So this is doing for every every function in the file, even if you didn't put anything on it, it just says, look, make do my basic sanity checks of like you can't do this. Even if I did something so even if I just did this, right? It would still do the same thing. Take five, like this would fail at runtime, definitely. Um, and so you can't, right?
SPEAKER_00So do you also get uh domain errors when you try to uh call something that's accidentally negative? It's like when you try to uh reset for a negative shape.
SPEAKER_03That is a great question. Let's well, you can reshape with a negative shape in Wii US.
SPEAKER_00Oh okay.
SPEAKER_03Um I was trying to think so theoretically, yes. I'm sure there are some examples of that. Um I can't think of any off the top of my head though. Yeah, because some things know that they need to take some things know that they need to take specifically natural numbers, and so it and it has a distinction between numbers, real numbers, integers, uh naturals, booleans.
SPEAKER_00Um I guess uh string versus uh numbers is uh easier to synthesize.
SPEAKER_03What is?
SPEAKER_00Yeah, you know, an example where you're trying to you know re-reshape something into the symbol of a string, which uh doesn't make sense.
SPEAKER_03Sure. If I if I I mean I'm pretty sure that'll work. If I do reshape i, yeah, yeah. Expected array of uh integers but found array of characters. This at sign means um ASCII, whereas if I put like, I don't know, um it says U for Unicode.
SPEAKER_00Ah, nice. That's very nice.
SPEAKER_03Um yeah, so that's basically that feature. It probably needs only somewhere, but I think some people are using it already. It's basically good right now for like your sanity checks of like make sure this thing takes this kind of value before you even bother running the rest of the code and having it fail in some weird other place, right? Um yeah.
SPEAKER_00Yeah, I can really use that uh at work. Uh I use API at work, by the way. And uh yeah, we run into this like uh uh empty array and uh you know string versus uh character uh versus uh numbers almost all the time. You know, if it would be nice if you know we we can know something beforehand.
SPEAKER_03Yeah.
AdamI know that uh how would you how would you write if you uh if you want to check a larger array that's a structure of no as remind me again, we will has we were has type arrays and yeah, we have box arrays, um and it has what we call data depths.
SPEAKER_03So I can make a let's say just like a person. Person, and I'm just gonna give them I'll just take this simple way. Uh uh. And let's say they have a name and an age. This defines basically um it defines a module called person and then it adds a bunch of helper functions and things um that may have a name and an age. I can make one, I don't know, it's Dan, and Dan is 31. Um, this essentially just makes a oh that's not supposed to look like that. Um this essentially just makes a box array um shape two um with these things in it. If I unbox it, it will um uh Max, I think you're going. Um it'll give me my values back. They're labeled.
AdamUm but then what just happened? What was the result you got back when you unboxed it?
SPEAKER_03It's two different values and they both have labels on them. Labels are like a piece of metadata attached to Ah, that's what's happening.
AdamOkay, we can't interact with the labels. They're for right, okay.
SPEAKER_03Yeah, yeah. Um, like if I do this, you'll see multiple lines. Um so there's that. Now, and then the module, so person, it lets you call it as a function to construct the thing. Um, but then if I do name here, um, it'll give me the name back. And this is essentially just a function that like um gets the item out, unboxes it, and removes the label.
AdamAnd so this is essentially assigned to the name directly if you wanted to update the name after the fact.
SPEAKER_03Oh, sure, sure. With um with the the inverse system, you just do um set person name uh Alice. Boom. Now it's updated.
SPEAKER_00Oh, yeah. Okay.
SPEAKER_03I can I could get into why I could get into why unbuy is an update operation. I'm not gonna get into that right this moment.
SPEAKER_04I guess but okay.
SPEAKER_03Uh we can we can do it if you uh we talk about it if you want to. Uh maybe that is probably a newer feature since the last time I was here. Um it's it's a logical, it's essentially a logical conclusion of the inverse system um that this should be true. This is how this should work. Um, but it's a lot for a lot more than just this. Um but there's that, right? Um, so person has a T field currently. So let me if I can get rid of this. This is the type, and this will work with validate. So person is uh an array of any size of any item and an array of any size of any item. If I um because these are uh character arrays that are stars. Um now if I specify okay, name must be a stir and that'll format for me. And age must be a um a uh a scalar number. I believe this is how it works. Um I put it like this. I think so. And I should just be able to say, um, is that still gonna work? Oh, sorry, I have to type validate here. There we go. Invalid type specification. Interesting. Oh, I have to go like this. There we go. Um, so here is person's type specification, and if I validate it, it works correctly. Um and so this can be used. Notice here that this type specific, I could have typed this out manually, right? This type specification is not about what is the scalar type and what is the shape. It is about what are the inner type specifications for each of the fields. So if I add another field here, I don't know. Um I'll just call it items. And it's gonna be a um, I guess just a list, a list of something. Um that's a good idea. Can we not do that? Oh, I have to type it in. Uh and cool. Oh, it has to be a box array. There we go. Um, so I can do this. Um, and then oh, I might have some things to work out on parts of this.
AdamBut if you could go back back, I'm not sure I was following it tiny here. Uh sure I should go back to the previous one here that was that did work. So so we're saying uh okay, it's say it's saying the signature of the person.
SPEAKER_03This is the value, and this is the sort of signature of the yes, this is the value of this person I made, and this is this down here is the result of person.t. Um what is it?
SPEAKER_04So I have said two here.
SPEAKER_03Uh the at sign is a character. So type like um scalar type value specifiers, these are just this right here is a built-in constant that is just itself. So if I type char, you can see what it is. This is a constant that is the character that it is its identifier.
AdamUh okay.
SPEAKER_03And it's just a you can just type it like this, right?
AdamOkay, they're actually the same. It's you you've written the syntactic sugar for for at uh double struck R is just R. Okay. Well, R is a function of returns.
SPEAKER_03Yeah, and this is the same like constant system that a bunch of other stuff uses.
AdamNo, no, then now I understand that. I was just I didn't understand where that came from.
SPEAKER_03Yeah, I should have I should have validated that, yeah. Um so this is saying like this is a list of some number of a Unicode characters. Yeah, now I understand what I'm saying.
AdamYeah, it's just the ad that confuses me.
SPEAKER_03So yeah, I so this is um I guess saying, okay, this is the first field and this is the second field. These are their types. Um validating is part of that.
AdamYou you can make a fixed width field by just putting a any number there.
SPEAKER_03Sure. Um, if I say your name, your name must be exactly uh three characters, sure, why not? And then I don't know, Danny won't work. And this could be recursive. So you can nest these and it'll just get more and more complicated, but the validation itself is recursive and it'll just check them all. Um and if I make a function for this, call I don't know, I'll call F and I'll put my little types back in there, and I'll make um person name. Oh, it is not. Oh, sorry, it uh it's I need to fix this. This is not failing, it is just aliasing when it shouldn't be. There we go. Um give me a list of boxes. Oh, I don't know. Validate it takes in a person T. There we go. Um, so this takes a person in and it gives you three characters. I'll go back to this. There we go.
AdamIt's it's literally a a character. Okay. Yeah. That's interesting, the the pricing.
SPEAKER_03Yeah, yeah. Um, so there's all that's basically how it works. Um, there's a lot to work out still with this. That's why I do want to have this probably in the language. I don't know. On one hand, it's really cool and it's definitely useful. Whether it should be like part of the language, is I'm leaning toward yes. Um, but I'm not 100% yet.
ConorIt is very cool whether it ends up in the language. I mean, this is and this is a kind of a novel space, right? There's not a ton of array languages out there that are experimenting the types of sites. Like I know that Ramora, an individual by the name of Justin Slepak, that did a PhD dissertation on a typed J at one point. Um and I think there's like a couple other out there, but they're all nothing in like a quote unquote if we can call Wewa a mainstream uh array language. Nothing in like the kind of the um the array languages that people are using. It's a very, very cool area to um and even like the just the type check at the top, you know, for a beginner that is just trying to experiment with glyphs. Not not that they're writing any production code or anything like that, but as a learning tool, I think it's very cool. It's it's similar um to the uh what do you call them hints that you give that I I've even like a couple times, and it's you you close them so quickly, I'll I'll I'll ask for like, hey, it would have been great to have a hint for this, and then like literally like three hours later you've merged it in. Yeah. Where like those that's something that I want in every single array language, where if you make a suboptimal you know composition of four things and there's a single primitive for it and it's just not in your toolbox yet, a lot of times WeWah pad will tell you, hey, you can use this. And you're like, oh my god, that's amazing. Like uh I just learned something in like less than a second because of the um what do you call it? Like compiler-driven um what was the the diagnostics. Yeah, yeah, exactly. Like that anytime you can get some kind of feedback while you're coding, uh, it's just it's such a a wonderful learning experience, even from someone like I've been doing this for years, and I I still love that kind of stuff.
AdamBut that there we has a strong uh advantage in in the being strict in in valence, right? This is incredibly difficult to do in those more dynamic languages. You can sort of see an artifact of this uh in in dialogue, which highlights what we call idioms, but actually what actually means is phrases that the interpreter takes as a single instruction rather than being consisting of uh individual parts.
SPEAKER_03We went we do have a page out too. Um it's actually not this one, it's it's the optimizations, which is like all the stuff.
AdamThat's why that's why I had this caveat with the with the name idioms. It's not idioms, it's actually just optimized phrases or recognized phrases or something like that. Um so but the interpreter itself does syntax highlighting as well. It knows what's going on as much as you can know what's going on. Uh nevertheless, it highlights wrong. And even setting aside the highlighting, it actually optimizes wrong. And occasionally you can get better performance and dialogue by inserting a no-up function inside of an expression to prevent the interpreter from recognizing what it thinks you're doing, because it then tries to prematurely optimize for that thing it thinks you're doing, only to discover at runtime that that's not what you're doing, it has to backtrack and reparse. Um so it it is really difficult. You don't need the more dynamic the language is, and an APL is here worse than say BQN, because you can't really you can't know the even the the syntactic class of anything until runtime. Um you can try to do like a code defense type thing and do analysis analysis, but that it's not always quite possible. And certainly when you if you're writing nasty code, you can fool the system in various ways. So it would be very difficult to yeah.
SPEAKER_03I've had a good amount of optimizations that I've ended up removing because I've realized that they're not actually sound. Um a lot of those have to do with like um execution order of things, right? This optimization only works if the functions are pure or something like that. Um stuff like that. Um cool. That's types though. Um there is a third big so all the three big features, like I said, in 0.19 are experimental. There is a third one um that is the least I think it's really cool. Um others, some other people think it's really cool. Um, I don't know that it's worth like. Like putting in a language and not just having as a library. But I can show that one too. And that one is where is it? Geometric algebra. Do you guys know anything about geometric algebra?
ConorLet's assume. Yeah, let's assume we don't. We know Max does because he's got questions. But I mean, and by assume, like I don't.
SPEAKER_03So I'm just um so geometric algebra is a it's hard to let's it's a whole system of math that deals with objects called multivectors. Um these are vectors, but also things that are very vector-like, um, that have magnitudes and directions in different ways. Um, and it kind of unifies um like a bunch of different transformations and a bunch of different operations um into one much easier to use system. And this this tutorial I have here on the experimental page on Wea, the WeGo website, um, shows you one of the applications you can use for this. Um the main idea though is that the same object that represents like a vector or a point can also represent a rotation or a translation or a bunch of other things. And it's not just good for like geometry, it's also has a few other niche applications. Um the other one I can show down below is like um auto differentiation, which is kind of cool. Um uh the basic idea is that there's a special operation called the geometric product, which when used on two vectors has a useful result that can then be applied again to other vectors to make use of it. Um so the example here, I'm not gonna like go through the whole thing. The example here is using it to rotate a cube. I want to make a um like a like an animation of a rotating cube. And to do that, right, you have to do um one, you have to set up all your like your cube geometry. That's the easy part. That's easy in an array language. Um, and then you have to do projections and intersections onto your like camera plane, right? Um geometric algebra is very good at projections and translations and rotations and things. Um so what this does is we generate all the points of a cube and well, we start with a square actually, because we do this in two dimensions before we do it in three just to show. Um, so here we I don't know if you can see it here, but there's little dots on the edge. I'm just making my cube a big point, a big cloud of dots that make a square here. Um and then um it uh turns them all into these multivector objects, which in this case are just vectors. This this E notation is something you'll see a lot in geometric algebra. You can think of these as like X and Y essentially. Um, but you're gonna have things that are like E1, two, which is gonna be a different kind of uh higher order of vector. Um and then I generate a bunch of rotations, and then I apply all those, turn all those rotations into multive vectors, and then apply them all, and eventually I get this rotating square. Um, this could have just been done with complex numbers. In many ways, multivectors are a superset of complex numbers. Um, but then what you can't do with with complex numbers is go up a dimension. And the way that I wrote them for Wiwa, they are totally like dimension generic. Um so here basically what I do is I make I turn my code that makes a square into a code that makes a cube, and then I do the same rotation just in one more dimension, and then I project it onto a camera plane. Um, and this I think I did a pretty good job with this tutorial if anyone's interested in reading like all the steps it takes. Um, but eventually we get this nice rotating cube with a uh perspective projection. Um and I'll make it a little bigger just to make it easier to see, um, which I think is cool. And then I show that, oh, we can actually um we can try it with different rotations, and it all it is is like a rows operation of different um projection axes, right? Or we could do it in all the all the axes at once, and then we have this very fast rotating cube rotating along some bigger uh mixed axis. What's really cool about this is you can go even further and you can project uh a hyper cube. And so here I didn't it doesn't go through it all, but here's the example that like does the classic like Tesseract rotation. I can make a little higher S too.
ConorUm and I just think it's a bigger as well. This is looks so crazy.
SPEAKER_03Yeah, um I'm I'm sure you've seen like the rotate. Here I'll make it a I have not.
ConorI haven't found this corner of the nerd in the case. No, no, this is the first time for me.
SPEAKER_03This is the classic, this is the classic visualization of a rotating hyper queue, like a four-dimensional analog of a queue. Um and this is a good amount of code, I guess. Um, but I think it's cool that um you can do this. In many ways, multi-vectors, or at least in this type of application, multivectors are um they're a replacement, but also I think they're kind of isomorphic to um like matrices, like transformation matrices. Um, I personally find them easier to reason about, uh, but that's just because I'm not really big into linear algebra. Um, yeah.
ConorWhat was the motivation? This is so cool. What was the motivation for this? Is it was there a corner of the Weewa community that was you know pounding saying geometric algebra, geometric algebra?
SPEAKER_03I forget no, there definitely wasn't. Um people definitely want like complex numbers, and that's why I added those a long time ago. Um, but I think I just learned about it and I was like, this is actually a really cool system, but it's only good if your language has like like you can have like libraries that support this well, but it'd be really cool to have it like first class and support it, um, because you can do lots of cool math stuff and visualizations with this. Um and so I learned about the topic, I thought it was really cool. I watched like hours of videos about how it all works. Um, and I really like the idea that you can take these same algorithms that because because if you do like um like in normal geometry, your like intersection formulae can look very different depending on like the number of dimensions and things you're in, or the kind of things you're checking for an intersection in, or same thing with like projection algorithms stuff. The formulas end up looking very different, whereas in in geometric algebra, they're all unified. Like a projection of any object onto any other object looks is the exact same operation in any number of dimensions in geometric algebra, which is really cool. Um, you don't have to bother with knowing how many dimensions there are, or even a line onto a plane, it's the same as a plane onto the plane, is the same as a point onto a line. It's all the same, um, which is really cool.
SPEAKER_00Geometric algebra is uh linear algebra done right.
SPEAKER_03Yeah.
SPEAKER_00I was uh kind of uh I guess a mad that uh I only learned it uh uh after being told uh no these uh workarounds and lies uh in a standard linear algebra, like uh the cross product that's uh the worst of vendor.
SPEAKER_03Yeah, yeah. So this has like what the what the wedge product. So there are some special glyphs in here that are sp only basically they work on everything, but they're specific to geometric algebra. This one is the outer product, um, which is like the wedge product.
ConorWhich is the report.19. And you can do that. Whether this needs its own glyph is I'm not sure, but because yeah, you have table, which is the beautiful window, you know, four quadrants. And then I saw this and it was called outer product, and I was like, whoa, whoa, whoa. I thought Wewa's name for the APL outer product was table, but now there's a new one, and I was thinking, what's the difference?
SPEAKER_03Yeah, this count should maybe be called the wedge product to make it more um thing. It's kind of like the cross product, but way better. Um there's another one called uh I believe it's called just inner product. Um if I show my experimentals here.
ConorYeah, I saw that as well.
SPEAKER_03Um this one right here, which is another geometric algebra operation.
ConorFor the for the audio listener, we have outer product, which is a cross, which is like the X. I don't know. I know that there's like relationships. Multiply. The multiply, yeah, with a line under it. And the inner product was uh the multiply with a line with a dot over it. A dot over it.
SPEAKER_03Those are not normal notation. Um, it's what I could find in Unicode that I thought felt right. Um, and they work here. Uh one of the other cool applications of uh geometric algebra is auto differentiation. Um so it can define the derivative of some function. Um already has an experimental derivative operation, but I just thought this was a cool demo. Um that uses, I didn't even add any features specifically for this. It's just a thing that falls out of geometric algebra that's really cool. And so basically I have this function f um that is like a polynomial, and then I hand implement the um the derivative of this polynomial, which is another polynomial. Um, and then I show how you can use like a very simple geometric algebra operation to get the exact same thing based on it. Basically, if you run the original function on a specific kind of multivector, um, you can get the derivative without having to figure out the derivative yourself, which I think is very cool.
ConorSo is is uh the inner product and outer product are these two glyphs that go hand in hand with geometric algebra? Is that how we should think about it?
SPEAKER_03They have different geometric algebra operations, but yes, they're only really useful in a geometric algebra context. They they do operate on normal numbers, but they're basically just multiply. Um, for complexes, they're they're slightly more nuanced, but they're basically still just multiply.
ConorAnd I I have a like on my list of books to read is this book on linear algebra. Should I be replacing that with some geometric algebra book? Apparently, if Max is saying this is linear algebra done done.
SPEAKER_03Pretty biased. I think it's pretty good. Yeah.
ConorAll right.
SPEAKER_03Theoretically, also you can store certain transformations in less space in G as a multivector than as a matrix, but I don't know. Um that is the feature. I don't know if this is gonna make it in to not to ever not experimental. Um, but I think it's very useful for these kinds of like cool visualizations and things. Um yeah.
SPEAKER_00I think uh these uh geometric numbers uh are as fundamental as uh complex numbers, which uh uh dialogue supports as well.
SPEAKER_03I know um NARS 2000 has um uh octonians, which is also which are also not good. Um and this is like the way better version of hyper some version of hyper complex numbers um that are actually used in different.
SPEAKER_00Use use a geometric algebra, forget about a complex octonius, quaternious. It's uh just the under one uh you know the framework.
SPEAKER_03Yeah, exactly. All right. That is the biggest features of, and they're all experimental, like you said, of 0.19. There are a lot of other little things. There's a million little tiny things. Depends on how much tiny is relative. Uh, but there are a lot of other little things.
AdamHow do you do uh everyday? Well, I I understand that the there are issues with the equatorians, luxonians, and and even there's another name for the ones with 16 dimensions, whatever over there. That's like useless. Um but uh be that as it may that that the geometric album might be better, it's fairly no common to need to do mathematics on just normal complex numbers. But does we actually do that?
SPEAKER_03Like have complex numbers?
AdamYeah, yeah.
SPEAKER_03It's had them for a long time.
AdamI mean, I'm not I'm not a regular weaver user, so I don't know. But I can imagine that I'm not the only one with this question.
SPEAKER_03Sure. Um complex. Um what uh one, two, three. It's uh it's a pervasive operation too. Um so this makes the uh four and one i, five and two i, six and three i. So the complex is the first argument, and the real is the this argument. Um you can also write them if you want to. I could write like um four, I think it's four r i five r two i six r three i.
AdamAnd the real and complex uh thing, but but if I take the square root of a negative number, then ah yes, so it will not automatically convert because it's not so um square roots on a just normal negative number is negative.
SPEAKER_03Yeah, um it doesn't check, it's not gonna check your numbers um to see if they can be made complex. And also you don't want to check, I don't want things that the type output is based on the input values because in the output, if I did this, for example, um like if I if I put some my negative number in a list with a bunch of other potentially non-negative numbers, I don't want it to have to check all the numbers first and then conditionally output complex or real. I want to just short. However, if I do if I make it complex myself, um it will give you the complex results.
AdamSo okay, so so we was basic numbers are floats. Is that how it works? Yeah. Okay. And but then you don't you don't auto-convert types like that.
SPEAKER_00You can also do uh e12 under experimental, I think that uh returns uh i as well.
SPEAKER_03Uh yes, because oh there we go. Um e1, well it is i it's a e12 is a geometric algebra multivector that is um has all the same properties as i basically.
SPEAKER_00But it doesn't special case uh under this uh uh e12 uh system. Yeah, it is. Do you have uh types uh uh for complex as well if you want to type check it's on complex number?
SPEAKER_03Sure.
AdamUm there's that it actually considers i and e12 as equivalent if you compare them, even if it's yeah, like if oh does it?
SPEAKER_03That's cool.
AdamYeah, but it's interesting because they are sort of distinct in identity, so they're sort of like positive and negative zero type thing, right?
SPEAKER_03Currently uh multivectors are considered the same like type as complexes, or or rather complexes are considered multivectors. And so like a type of these uh type of i and type of e1, two, is gonna be evaluated the same. Their representation in like internally is different, but um these are considered the same. Uh the the built-in complex numbers are gonna be way faster than the multivectors currently.
SPEAKER_00So uh you added uh geometric algebra as an extension, right? It's not uh breaking any existing logic with complex numbers.
SPEAKER_03Especially because it is um experimental. And also by having hard-coded complex numbers, you can they're so much faster. Um multivectors can be kind of arbitrary size and can take up a lot more memory than they necessarily need. And if all you need is complex numbers, which you do um a good chunk of the time. I I use them for I use them for stuff you wouldn't. It's a sort of thing, and this is uh kind of a philosophy I have about adding stuff to the language. There's a lot of things you can use elegantly to solve problems that you wouldn't always do. Like you would, there's a lot of things you could use to solve problems that you wouldn't import a library for. But if you just got the thing there at your fingertips in the language, it's a good, it's a cool thing you can use. Um so I've used complex numbers for like um what's good? A good example is like um if I have some list of numbers, um I don't know. Actually, I'll just make a range. If I have like a range of numbers and then I do like uh range raise i to all their powers, um I'll just round so we can see um I now have like directions and I can even like uncomplex these and then uh make my these nice vectors of like all my offset directions. And if I want them to be specific directions, I can just put a bunch of different numbers in um and it'll give you that. So there's some cool applications of complex numbers for things. Um we also have like complex number image output and stuff, like a visualization of your complex fields and things.
AdamUm and and your complex numbers are just paired floats or yeah, with all the operations.
SPEAKER_03Um a couple other small things from 0.19 is like um all uh in the past we've only had like signed. Um it's not there we are. Um we now have like named stuff for all the I don't know why this device is such a weird decimal. Um but we have uh named versions of all the trig and hyperbolic trig or hyperbolic functions.
AdamUm so yeah, the the reason you have the odd numbers because it's all essentially zero with a rounding.
SPEAKER_03Yeah, it is. Um so you just got like cosine, sine, tangent, and then like all the hyperbolic ones and all their inverses.
SPEAKER_00Huh. That's an eta uh tau before.
SPEAKER_03Quarter pi. Sorry, quarter quarter tau, quarter tau.
SPEAKER_00Yeah, the support for tau is also uh very insightful. That's another you know, uh map I was trying to use in school.
SPEAKER_03Um we do have tau in there. Right. And I use this, I use tau mainly for and you can do write stuff like I don't know, tau report and potato.
AdamThat's cute. Um what it does is does it has like fuzziness factor or something to make this work?
SPEAKER_03Or I mean if I type like like if I just type typing out enough digits of pi eventually 2253 five eight nine?
ConorLook at this nerd flex right here.
SPEAKER_03There we go, there we go. I typed in enough digits of pi, and it's like, oh yeah, that's just pi.
AdamOkay, but that mean that mean uh hold on, but you said that doubles. Okay, so uh if you have to type out every single digit to be precise, 17 or something.
SPEAKER_00That's like possible exactly as no desist of a pi.
SPEAKER_03Oh, look when I when I took out a digit, it says it's about pi. Oh it really seems like it's supposed to be pi.
AdamOh, okay.
SPEAKER_03Um there's a lot of things like that. If another likes uh square root two, it's just like oh that's square root two.
AdamOh, so uh okay, but this is not actually symbolic algebra, it's just faking it.
SPEAKER_03But it's just yeah, it's for stuff that really looks seems like it's supposed to be something it does that.
SPEAKER_00Yeah, if it has rationale, so why not add uh the same support for rooted numbers? That's uh answered that's a cool idea.
SPEAKER_03Yeah. Um, I think that's I have like blog posts for every single release. If people want to like know the main features from that, um I can't quite some of the uh it's uh voxel support.
SPEAKER_00Uh is it in this version too?
SPEAKER_03Uh yeah, that's now that's from a few versions ago. Um, this is a great visualization tool. Um so what it is, is a built-in renderer that turns your arrays into images that are like voxels, like like three-dimensional pixels, and it renders them from a certain can camera angle. It's good for visualizations or making quick little stuff. This is another idea. This is still experimental currently as well. This is another example of if it's there at your fingertips, it's easy for you to reach for. Um, I'll give a quick example. If I make just a random array, um, I'll just generate an array of um 10 by 10 by 10 um with a random seed. Here's a bunch of numbers, and then I'm gonna round them. I'll make them a little smaller. Basically, I'm just generating a bunch of a three-dimensional array, a bunch of ones in some places, but mostly zeros. Um, there it is. And then what I can do is I can call this voxels function. Um now it's very small. I'll make this a little bigger. I'll make a hundred, well, let's do 30 by 30 by 30. So you can kind of see this cloud of points in my example. But what's cool is that it has this is another feature that's been around since I think a version or two ago. Um, is that some primitives, but also your own built-in functions, can have optional arguments if you turn them into uh modifiers. So if I do actually I want it to be bigger, I want the scale to be three, I want there to be a fog so that it's easier to render, and then I can see, oh, there's my there's my array. Here's a let's make a little starser here. There's a bunch of points there. Um and I can do cool stuff like if I want to render it with um rotation, I can do um just make a quick rotation array. Um, I don't know, maybe 20 frames, and then I will uh do a camera position. And we should oh, and I have to do a row zone here. Maybe that's a little quick, uh, maybe like 60 frames. There's my cool like visualization of this rotating cloud of points. Um I just like that for quick and quick and dirty like multimedia visual visualizations of stuff. It's uh we can do color, it can do transparency.
SPEAKER_00Yeah, yeah. I can't think of another language that can uh get this done in this uh Q code.
SPEAKER_03Yeah, I like applying it to other certain things. Like if I go to say the game of life example, I can then just take this and be like, oh, turn it, uh just turn this whole array of the game of life. Uh I'm not gonna upscale it here, I'm just gonna do like voxels, uh set scale. I'll do like three. I think that should just work. Um, and then I'll and I'll do some flock. And so here's like my whole visual three-dimensional visualization of the the lifetime of this game of life simulation, which I think is cool.
SPEAKER_00That's awesome.
SPEAKER_03Um this is one of like a few other experimental features. Another one is like noise. So if I do like noise, and I think I want seed zero to two octaves, and then I'll do like times two this this basically given some numbers, um, it generates um corner right. Do I have this backwards? Um, I might, I shouldn't. Maybe I'll just go to the examples for this for this thing to know how it works. Um so it just generates basically perlining noise, um, which is useful for a lot of other visualization things or like cool simulations and whatnot. These are kind of like the edge features. They're like other like more array-esque language features I could go over. Um, I could talk about if you guys wanted to, why unbuy is a set operation, like set this thing um about this thing, and conversely, and also anti buy, which is similar.
ConorUm yeah, definitely. I'm I'm curious to hear that.
SPEAKER_03Uh sure, sure. Um, so uh the unmodifier has the rule that the resulting modified functions signature. Must be the opposite of the input. So if I have a say couple function, uh like couple two numbers together, um uncoup that takes in two arguments and gives you back one. Uncouple must take one argument and get back a two. So if I have something like um uh the by function, the by modifier, let's say I do say buy pick um three out of my like array of numbers. So I'm pick would pick um the number three or the sorry, the third index three out of my array, and then buy uh keeps the original array around. So this takes in two values and it um returns two values. Um actually I should do one with buy action, uh with un instead of NT. So I'm gonna do first instead. So the function first gives you the first item in the array, um, and the buy operation keeps the array around. So this takes in one value and gives back two. If I do unbuy and then first, you are doing the opposite of this operation. And because uh the original unfur or buy first takes in an array and gives you back two results, this unbuy first should take in two results and give you one. So if I do say if I do unbuy first and then I do say some character, I can then put some string and then it'll set the first item in that string, which is cool. And so this is like an amend essentially. And if I wanted it to do it for um at a certain index, I have to use what's called anti-by. Um, there's a reason I can't use unby because pick is a dyadic function. Um, but it works essentially the same way. Let's actually do select for a cool. If I do anti by select uh like the numbers one and two, and then I'll do like the two, I don't know, two other characters into some bigger string. Um, we can see that it puts those characters in the given positions in that string. Um, this is a logical result of. I guess there's other ways that this could be implemented. This is the most useful, and that is a sound inverse. Um and so this is just one of the many ways that we uses inverses to make a bunch of operations available that you don't need new primitives for.
ConorOmniCar in the chat is saying show them unbuy ddope or unbuy classify and or.
SPEAKER_03Uh let me see if I remember how this one works. So ddup is this is one that like I did not know about until someone showed it to me. It's one of the benefits of having like an emergent system of inverses. And so ddup, uh, what's it actually I'm gonna do like this. Uh here's one of my favorites. Lego helmet is a good DDP thing. Um so ddup just deduplicates duplicate items in an array. Um, if I remember, so by ddup keeps the original array around. And if I do un by ddup, I think if I just put numbers here, I think I need more numbers. Six, seven, eight, nine. Okay, so this is saying if you were to if the let's see, there we go. It's saying if one, two, three, four, five, six, seven, eight is the deduplicated version of something, re-duplicate it so that it would be reduplicated in the same way this string that I'm deduplicating is. And somebody showed this to me and I'm like, what is going on? How does that work? And they're like, Why don't you know? And because I didn't actually, I implemented this is basically um unbuy and anti-by use the same hook into the same logic that under does. And so when I implemented under deduplicate, I essentially implemented this um as well on accident. Um and so there's a lot of anything that can be under essentially, or most things um can be unbied or anti-byed depending on their signature. Um stuff like that.
ConorVery neat.
SPEAKER_03So I mean I could go over line, but I don't know.
SPEAKER_01This is the same thing as a self index in the index into the unique.
SPEAKER_03Um, I don't know. I guess, yeah.
AdamI guess if you took your original string and then you did um you find the first position of every element and it's in the unique elements.
SPEAKER_03Oh, it's not class, it's um occurrences, oc one. All right, there's the unique ones. And then it's see the thing is is it's not just a keep on this number. It's this is not a mask that used to filter. This is reverse this filtering.
AdamYeah, like if you if you take if you deduplicate Lego helmet, yeah, and then you look up the Lego helmet in the in that look up every uh every character when it what's what's the position of it across.
SPEAKER_03Oh you're right, you're right. So if I keep that and then I do like index, I think it's actually this way, like this, and then oh, and and then I take this and I I I use that to select on there, right? Or no.
AdamNo, it's like look, I don't know how to compose things like this in in Wea, but I want to look up uh the position of L in the deduplicated Lego helmet. I want to find the position of E in the Dego.
SPEAKER_03Like okay, so we have zero, one, okay.
AdamYeah, L is at one, E is at just increment by one. I don't know why it's off by one, but that's oh, because the numbers you gave. You you counted from one to eight, but you should have counted from zero to zero to seven, right? Then we would have gotten the same.
SPEAKER_03If I do this, right?
AdamYeah. Yeah. That's the same thing.
SPEAKER_03Yeah. Um, so yes, you could do this. Um I think this is mildly more in well, I don't know. I wouldn't, I don't know if she'd even use this for. I it was just a funny thing that happened recently of something that I didn't know aware about.
AdamThere are there are many computations that are cheaper to do on indices into the unique rather than doing it on the data itself. For the characters, it might not matter so much, but if you've got some large array, complex arrays, and uh you all you need to do is is deal with their um their relations to each other rather than the data itself. So you can use their sort of ID tags instead of using the array.
SPEAKER_03That makes sense. I mean that's why a case where you might use under deduplicate.
AdamUm, but if you but that's only if that's if you want to go back to the data at the end, but you might not even want to do that. You might end up with some grand uh uh conclusion about the data.
SPEAKER_03Yeah.
AdamUm all right, I can pick through the self-index is not the same because you don't get a uh you don't get a permutation. Uh not permutation, you don't self-index can skip elements, right? When you've got duplicates before the first occurrence of some element, then you don't get consecutive numbers. So it's not the same thing as a self-index.
SPEAKER_03I think that makes sense. Um I'm trying to think of any, I guess like some of the biggest ones. I I don't think this was the case last time. Um, in that I've basically entirely moved away from any language about a stack, and all the functions that most of the functions that would have manipulated a stack are gone. Um so like there's no duplicate, there's no flip. Um those have all been mainly superseded by um modifiers. Um primarily because it is an easier way to both well, it's an easier way to conceptualize um tacit um data flow uh is to keep it rather than like say duplicating a bunch of arguments you're gonna need later, then you have to remember the order of the stack as you're going instead of do duplicating a bunch that you need for later, you use on or by or with or off, which are these four modifiers that do very similar things.
AdamUm and so this sort of addresses a thing I think I mentioned in an earlier episode that that bothered me about the fourth type language. If I realize later that I need some value from earlier on, I have to go back in the program and duplicate at that point and then keep track of where in the stack is that value going to be until I need it.
SPEAKER_03Yes, this large I mean it doesn't entirely address it, but it like addresses I'd say like 80%. Um so these are just four modifiers that are various sorts of combinators. I don't think they're combinators that make a ton of sense in, I guess they would make sense in the classical like tree-based combinator sense, but they are multi-output. They do make your function multi-output, even if it was just single output. And so I mean, I if I if we're interested about just like what they do, right? Um, if I just whip them up real quick. Um I think we probably know I think you guys probably know most of these, but we've got like these. Um there's like self and and backward, which are like duplicate and flip essentially. So you've got like yourself, like say couple. Um that'll put your things together. It's essentially uh is that the W combinator, Connor? Or is that C? It's the W combinator, yeah.
ConorDupe.
SPEAKER_03And then C is the uh swap. C is the flippy one.
ConorOr not self, yeah, swab, uh or commute.
SPEAKER_03Oh yeah, yeah. Um it's called backward and we went. Um so with the combination of all these, there's also like below, which is just some other things, and then also these other sort of um argument management modifiers. Um, we I think we mostly solve a lot of the tacit problems. There's still some stuff I need to address. I have some like it's currently in the work, some experimental non-tacit stuff that I'm leaning toward not adding because I just it makes me feel bad. Um, but yeah.
SPEAKER_00What did uh your users say react to this uh deprecation notice? Were they happy or about what about uh you know this uh removal of uh you know these uh stack functions?
SPEAKER_03Um I think by this time people were mainly writing in this style anyway, so it wasn't a big deal. Yeah.
AdamSo this brings us to a question uh sorry, go ahead, Max.
SPEAKER_00Yeah, I'm asking because uh um I stumbled upon Netherlands uh uh page for we we love like the designs and uh I saw like there's like some uh great uh uh retirement uh meme about uh you know these systemica functions and no I know I wasn't I wasn't sure what uh what the design was about.
SPEAKER_03Is it the is it the one with a bunch of blue a bunch of blue symbols on it? Yeah that is such an old niche joke that it's crazy to have like a shirt for. Um that that's like a very old notation when I was really trying a bunch of stuff out. Um the language that I uh in the past like I'd say year and a half, which is I think the last time I was here talking about it, um has been in much less flux, I will say. Um mainly because I have other stuff I have to work on, but when I do work on it, I'm not changing like big huge things, right? I'm not changing like the fundamental way you interact with it because I think we've mostly converged on a model that works. Um I'm mostly happy with it as I actually work on things. There's a few minor things here and there I might I might improve or change, but for the most part, I like how it works currently. Um there also aren't like a ton of like fundamental primitives that I think need to be added, really. Um the one that the one that people really want the most, um, that they might be annoyed that I'm so hesitant on is called uh reach, which is um I'm about to give you a positive couple. Uh given a function that takes there's a few permutations of it, but given a function that takes two arguments, um, it takes three arguments and it gets rid of the middle one, um, which is annoying to spell otherwise. Um, but my philosophy is kind of like you should ex you should spell it explicitly because it makes it easier to read. Um I don't know. That this is like the most fundamental one that might get added. But like any other array primitives, I think I'm mostly happy with at this point. Um version wise, like I do still plan to hit a 1.0 at some some stage. Um there's definitely gonna be a 0.20 and likely a 0.21, maybe a 22, but I don't think the I don't think we'll get much farther than that before uh a 1.0.
ConorThis is kind of a good or I was gonna say uh and I guess we can have a couple more questions, but I do have to wind down soon because the diapers are need to be changed at some point. Um but uh earlier in the chat, and this is kind of topical to what you're talking about now, Kai, with adding primitives, uh Chris C4TUBO in the chat asked, serious question now. Uh APL per atom is very slow and cautious when uh adding features, i.e. new primitives and other capabilities. How does Wewa decide when adding more? And it actually says is two with double O, but I clearly copy and pasted not the full question. So we'll just end the question in the middle of the question. But yeah, how does Wewa decide? Or yeah, when when you decide when adding more is too much. Adding more is too much. Yeah, that makes that adding it.
SPEAKER_03That's a good question. I mean, so so I feel like one, I guess it's not a question of stability. I was thinking it was, but it's not. Um, the main things are there's things like um, how used is this operation? How fundamental is this operation, like how hard would it be to implement if you didn't have it? Um, so for example, something like occurrences, which um I think BQN has. I don't know if APL has it. This is very annoying to spell, um, as far as I remember, um, if you don't have it, um, which marks each element of an array with which occurrence of the the element in the array that is. Um there's other things, I guess, like um, I don't know, what's a good example? I guess something like sort. Like you can spell sort with um select by rise, right? But like you use sorting is such a fundamental operation that I don't know, sometimes you just want it to be nice and short. Um there's also the line between like what is it? Yeah, yeah. Um there's also the question of like some things that I don't think there's a lot of things I don't think need glyphs, but are definitely like nice to have built in. So example that I just showed earlier is like cosine, right? There's not a oh my gosh, if there was a cosine glyph built in, like sorry, in in Unicode that was like this signed one except the cosine shape, I would use that in a second. Um, but like like tangent and stuff, like we don't need this, or like I have built-in JSON support, right? Um, where you don't really need like a glyph for JSON. It's it's it's so useful to have on hand, but like you don't you don't need a special symbol for it. It's not something you need to read as part of like array operations. So I have a ton of things like this that are just like words and they are built in, but they're not glyphs, they're not they're not like symbols you need to learn or anything.
SPEAKER_00Um would you like them to be symbols? That was uh quad names, like uh they they dialogue that literally has quadization.
SPEAKER_03Yes, I do have um there is a distinction in that in like if you go to the list, big list of things, you'll you'll see in all the what I call system functions, um, which have ampersand names in front of them. These are specifically functions that are they're built in, but they are dependent on the backend that you are working within. So there's like a default backend when you download the interpreter. There's like safe backends you can give if you are trying to like um embed WeWa in a broader like REST application where you can like block off certain operations if you want to. The web, uh like the pad on the web uses a totally different backend. So these things are all things that may or may not be implemented for your backend. Um whereas just the ones that have names that don't have ampersands in front of them are things that are implemented regardless of back end um that will always work, but which are probably not common enough to need like symbols. That makes sense.
AdamBut but but to go back to what Max is saying with APS quad symbol that introduces system names, that sort of exists in We as well, by looking at the capitalization. You really should be using capital letters for your and and for your own things and lowercase letters for for the built-ins.
SPEAKER_03And then yes, that's like the convention for although that wouldn't be, I don't know. I I I my understanding is quads in APL are a like standard library type thing. It's built into the interpreter, right?
AdamYeah, yeah.
SPEAKER_03I mean these are built.
AdamHold on, hold on, wait, wait, wait, wait, what did you just say? Are they they're standard library as opposed to built in? That's what you said?
SPEAKER_03Well, I'm asking uh which arch we should try.
AdamSorry, yeah, I misunderstood you. No, uh those things that begin with quad are always built into the interpreter, but that they're not necessarily the same across uh implementations of APL. You don't have the same sort of uh landscape of WiiWare as you had in APL, where there's there are larger differences between APL vendors and so on. But the ones that I have shared name now across vendors are usually the same or very similar to each other, but they always for every APL implementation, quad names are always part of the interpreter and never something you can plug in or or the user can't add any. So they are they have the same um role in the language as your lowercase built-in names here that don't have glyphs, have and and a potentially a uh a system name in in APL can be upgraded to become a primitive. It can get a glyph. And there are there are primitives and and system uh names that are the same, they're synonymous. So they are just word primitives in that sense. But generally speaking, it's for dirty stuff, is for the is the system names and for pure merry manipulation have glyphs, but it's not it's not a clear-cut distinction between them.
SPEAKER_03I agree, I agree. Um, and that's that's the same thing with like what what do you even make glyphs? It's not a clear-cut distinction of what should be. Um, in my mind, though, the glyph stuff is like all your fundamental sort of one, either some array operations like all these are, right? Your rotates, your sorting, your various indexing and analysis operations on arrays that are your like fundamental composable units that you use to make array algorithms. And then also, well, of course, all your math and stuff, and then all the things that you all the things that you use to like thread uh values through the program. Those are kind of like the most fundamental sort of operations that I do think it makes sense to have glyphs for, where most of the other things can be named, right? Right.
AdamYeah, I think we in agree agreement on that sort of thing with how APL does it. I think it sort of folds up naturally, but it's not always clear what something is.
SPEAKER_03Yeah, whereas a language, but although a language like say, like definitely APL, but also BQN are much more conservative with what they give glyphs as opposed to Wiwa, right?
AdamI don't think I don't think that's the case actually. I think they have the same sort of uh notion of what should be a glyph and what shouldn't. It's just that we were has a larger vocabulary of things. Um sort of things.
SPEAKER_03That's why I say BQ, I think BQN is generally more conservative than like APL is. Like BQN doesn't have partition. Partition is so useful for any kind of like text processing at all.
AdamBut BQN doesn't have it because you can spell it with group and for for group done, like it's not a difference of uh what sort of thing should have a glyph, only what should how big should the vocabulary of the language be? But they could all but then you can't even speak about APL because tiny APL supposedly is a type of APL that has a giant vocabulary compared to I mean a dialogue. Okay, but that's dialogue sort of falls in the middle.
ConorDoesn't Marshall have like an article, like literally where he talks about like principled versus practic practical or pragmatic? I always forget, and like he always says BQN is supposed to be principled first and foremost, whereas like Kai has mentioned on past podcasts and now that if something is inconvenient to spell, even if it might not be, if it violates like pure principledness, um, you'll put it in. And I I lean way more towards your perspective on this, Kai, because there are things in BQN all the time that like I'm constantly reaching for. Probably the most painful uh and probably the most often is that uh BQN has Windows, but doesn't have anything for doing NWISE reduction or the equivalent of Stencil in Tiny Apple. Uh and is it called Stencil in in Weewa as well, or is it tuples? Yeah, stencil. Stencil, yeah. And I think Stencil in Weewa was the first time I ever saw a two-character spelling of adjacent difference, which is like my it's it's I probably stuff like that shouldn't make me as well.
SPEAKER_03You made a video about that too.
ConorYeah, yeah. Oh yeah, I did, I did. It was the the Batman Dark Knight Rises, because it I like it literally, it was a highlight. I don't know if it was the week or the month when that happened, but I was like, this is what I've been talking about for folk for for centuries. And uh and then Tiny Apple has it now. And dialogue can spell it in three with the N-wise reduction, but BQN, it's like five. And like that just it breaks my heart because especially for certain types of applications, these adjacent comparisons, whether it's differences or uh equality may happen, all that that's why like uh Q specifically have differ and deltas like as keywords because they're so uh common. And those are specializations of the uh adjacent kind of uh operation. Anyways, the point being is that I definitely agree with Kai that BQN draws the line at principled and dialogue probably sits in between, although Adam can speak better. But from my view, dialogue sits in between BQN and WeWa. And like if I had my own, like I and that's why Tiny Apple a lot of the times is my because they just throw everything, Madeline throws everything in it. I love that, you know, if it's in it and I can reach. I don't I want there to be an all-equal glyph, which I don't think any array language would ever add. But like all equal, when you want it, it's just oh man, I gotta spend three or four characters on this, and it's just like it doesn't belong, but it's it's is a kind of thing that almost feels fundamental. Um, but uh yeah.
SPEAKER_03I have I have two optimizations for that. They're each four glyphs long, right? But they're optimizations, but they're not glyphs.
ConorYeah, and that's the thing. And so do these optimize to the same thing?
SPEAKER_03Yeah, they do.
ConorAnd that's the kind of like I even I even the the the what is it, not the irony, but like the over the Sega of my array language journey. I gave a talk like years ago um called Array, uh, what is it, array notation or algorithms as a tool of thought, which is a play on the uh notation as a tool of thought, where I showed like 14 ways to spell it all equal. And uh I I keep coming back to it, and I used it the other day, and I was like, wow, wouldn't I if a tiny apple had an all-equal glyph, it would have the same effect as the two-character stencil um uh that had uh you know, anyways, I'll get off my soapbox.
AdamUh I'm kinda you'll love my next talk at the dialogue. You had an all-equal dialogue before sort?
ConorNo, Adam, that's a big mistake. Use sort first.
AdamNo, no, no, no, no. That's not what I'm saying. I'm just saying that you're going to like my talk.
ConorOkay, okay.
AdamAnyways, um, but in K, even K that has like it has the strictest uh vocabulary, smallest vocabulary of any Amazonian language has an adjacent uh prior operator. Yeah, you can do minus prior.
ConorAnyways, we've got 10 minutes over, mostly due to my di tribe or soliloquy or whatever you want to call it, monologue. Um, any last things you want to mention? I feel like we should have you back because uh I know Max had a laundry list of questions, which I think we got to some of them. We got to the uh geometric algebra. Um, or are any any major features that were you just want to like mention for people to go look into uh in between dot 15 and dot 19?
SPEAKER_03Or should we just have you back uh for uh for another um I mean I can do a like a two-second scan here real quick. I'm sure there's some like big ones that I'm just like are not in forefront in my head, but were like big at the time. Um the main things that get added, right, are like subscript currently, uh lately are like subscript behaviors and then like inverses. Um and these allow for a lot of different stuff. Um, I don't know if we ever went over like data definitions, which is like my answer to structs at enums and stuff. Um, I don't know, I forget how long ago that was added. Um, or all like the Mac way you do macros and stuff. That's a whole thing. Um but yeah, I mean if you if you ever want to like learn, just know the features of Weewa, all the staple stuff is documented in the tutorial or in these other tutorials and docs here.
ConorPerfect. We will make sure to link to those. And they are they're amazing uh docs. Uh I can vouch for them because I spend much time uh learning about the new glyphs of Weewa when they get interesting. I guess we will say thank you so much, Kai, for coming on. It's been uh overdue and it's always fantastic. Um, lots of really, really cool features that uh have been added. And so we will make sure to link to all of the uh, you know, definitely the changelog that mentions all this stuff, but also we'll I'll go through when reviewing this to make sure that we we link to the different glyphs and validate and whatnot. So if people want to dig in more, they definitely can. And uh also thank you to Max for being our guest panelists for the day. We'll we'll we'll hopefully do this again in the future. And with that, I guess we will say happy array programming. Happy Array Programming.
SPEAKER_04Happy Array Programming.
ConorAll right, and thanks to everybody on the YouTube uh chat. We will see you in the next array cap.