s (⊢⍴⍨⊣,⍨÷⍨∘≢) v reshapes the vector v into a matrix with s columns and the correct number of rows to use up all of v. How would you simplify this train?
(it assumes the length of v is a multiple of s, cf. an example here )
making my bytecode generator use it will be annoying though (especially for variables from parent scopes, as there's pretty much no connection between them while compiling)
@dzaima You're talking about inputs and not the actual system variable •args, right? I think the variables defined in the header should be different from the special names for inputs. So for example {𝕊a:𝕩↩2⋄a} should just be the identity. Otherwise, what would you do about {𝕊a‿b:𝕩↩2‿3⋄a}?
@Marshall no, i'm talking about the actual •args, and the system that made it possible for a file containing x←•args, when executed, assign x in the global scope while not changing the global scopes •args
@Marshall a matching header 𝕊a‿b would work pretty much like a‿b←𝕩
@dzaima (i guess a better example would be that X←⍎ assigns x in the global scope, but X"•args" is different from •args)
(also the "special" 𝕨𝕩𝕗𝕘𝕣𝕊 are very much not special at all, except that they should (i.e. not "must") be in certain slots, and that the interpreter likes to write things to those specific slots)
@ngn Not sure that's really fair since APL has to distinguish between reshaping and nesting. BQN can do the same partition as K with (⌊2÷˜↕∘≠)⊸⊔, but it wouldn't count as a solution.
(i guess a way to implement headers in the bytecode would be to have a SET_ bytecode that, instead of erroring if it can't match, skips to the next header from some predefined table, and some mutable version of PUSH for just checking for equality)
@dzaima though at some point the whole ARRM system should be replaced with constants already just being the wanted arrays, though that's hard to generate in BQN itself as the mutable objects aren't ever exposed to it
pushed variable changes. Now there's LOCO/LOCM taking depth & index as arguments, and for •COMP each of 3⊑𝕩 must have another item of the variable names (including what's applicable of 𝕤𝕩𝕨𝕣𝕗𝕘)
@dzaima More boxing errors with e.g. 1+<0. This only happens when the left argument is a non-array; swapping the arguments gives an enclosed result.
On the plus side time ./dzref_full test/testref.bqn is down to 4.5s after implementing a decent sorting algorithm, down from like 8m. It got a little slower after those variable changes, I assume because the compiler isn't generating LOC* instructions.
Just need to get dzref_full to compile and then I can run mostly-BQN on anything that can interpret the bytecode and supports some very basic array operations.
@Marshall I have a mad plan to write a BQN compiler using Eiffel. It's a bit mad because I've never written a compiler before but there is an excellent lexing library that does BNF grammars available. My assumption was that the rational place to start would be implementing parsing of stage 0 of the spec.
But is that actually the most logical way to approach things after all?
(the lex has a corresponding compiler compiler as well)
@ab5tract Well obviously you want to do the tokenization first, but starting with parsing sounds reasonable to me.
If you have the parser working, then you can either compile to bytecode and run with dzaima/BQN at first, or implement the basic operations spec/reference.bqn (or probably dzref_full for performance) depends on and use those to fill in the rest until you implement them natively.
Ok sounds good. Not sure when I'm going to break first ground on it. First I'm going to make a few other odds and ends to learn the ropes of Eiffel before I dive into the BQN part.
Eiffel is quite a simple language in terms of syntax though, which is nice. Learning the whole 'design by contract' methodology is where a lot of the new-ness comes into play for me.
Also, in case it is of interest to anyone here, I just published a blog post that some here may find interesting. It lays out a bit of the non-technical aspects of behind the line of thought that lead me to very quickly put APL into a favorite topic of exploration: 5ab5traction5.bearblog.dev/for-love-of-the-underdog
@Adám In three dimensions there are corners (0 dimensions), edges (1 dimension), and faces (2 dimensions). With more dimensions there are more possibilities and it's not clear which of them are edges.
@ngn Ah, the ⎕io trick. Was working on something with a similar structure, and I even thought about |, but I don't have that option (but I can just add 1).
@Adám The point is that in 3D, an edge is, both a 1D thing and a (n-2)D thing, where n=3; if I understood correctly, Marshal wanted to know if "edge" was to be understood as a 1D thing for any nD or as an (n-2)D thing for any nD. Another example, in 3D we call "plane" to a 2D thing, which is (n-1)D, from which we got the name "hyperplane" for things that are (n-1)D inside the nD space.
@ngn care to go over this with me, please? I tore the train apart and I see what each part does but I can't understand the mathematical insight it capitalizes on
@RGS I think the only mathematical idea in anyone's solution is that we're counting the number of dimensions along which a given index is in the interior. It has to be 0 or 1 for an edge. ngn found a nice way to mark the interiors using |.
@RGS i assume you understand ⍳vec? ⊂|⍳ turns the last index along each dimesion into a 0, so we have 1 on one side and 0 on the other, and other numbers sandwiched between them. 1+.<¨ counts the 0-or-1s in each cell. the cell is on the wireframe iff they are fewer than 2.
@RGS Because it's a trick with ⎕io? It's weird because | is kind of inherently ⎕io 0, so mixing it with 1-based indices gives you this skew thing you can abuse.
@Ada here's a list of differences, though that might be a bit outdated
(ninja'd; the two main goals of dzaima/APL were to create an APL with things i wanted, and to learn APL (i started making it fairly early on in my APL adventures, re-writing every builtin is a pretty damn good way to learn what each does))
@dzaima Seems I actually misunderstood where the error message is coming from. I'm getting an ImplementationError after•COMP successfully runs for some reason.
Okay, I do have an error in compiling (cannot redefine "A"), but I don't know where it's from because if I try to print things as I'm running tests then I get a different ImplementationError.
right, another thing to try would be to do •compstart←0 or •compstart←¯1 to disable compilation or enable it for everything (the default is •compstart←1 which compiles to java bytecode when a function is executed >1 time; no compilation is better for debugging)
(also, make sure you're on the latest version, i broke java-compiled •← at one point, which'd get hit if you're •←ing at the same place multiple times)