Friday, August 14, 2009

Vector: New

This should be the post in this series which most reveals how much I don't know. (At least, I hope there aren't any worse than this!) Because the truth is, I don't really understand new in Perl 6 yet, and I completely botched the one member variable declaration. And yet the code all works, as far as I can tell.

So, coordinates is supposed to be an array of something number-like. Why the heck is it declared as a scalar? Damned if I know. In my head it certainly was. I didn't realize that it wasn't until I noticed when I was working on the last blog post. Everything works just fine, presumably because it is getting treated as a scalar containing an Array object, or something like that. Perl 6 just automatically did what I wanted, even though I'd failed to properly communication my wishes. I suspect it might have some impact if/when I try to make things ro, but for now I think I will leave it, at least until I have a real set of tests up and running.

As for the name, I've been pondering shortening it to coords. I think that would be just as clear, and make the code easier to understand just by getting rid of a lot of excess verbiage. This is particularly true for the cross product definitions. I love that the member name has to be tagged with a dot -- it seems a straightforward way of identifying the name as a member variable without adding some sort of tag on the name itself. (That is to same, it's not p_coordinates or m_coordinates or something like that which is a local naming idiom; it's a proper part of the language.)

Moving on, what the new code does is pretty opaque to me. I understand the function signature and how I am establishing a value for $.coordinates. But the $self and bless stuff is just boilerplate copied from the spec. I'm sure there is a rhyme and a reason to it, but it just feels like weird things left over from the Perl 5 way of doing classes.

My new functions here have evolved along the following lines. At first, I didn't have one at all, just using the default generated by Perl 6. I quickly decided that using that was ugly and awkward, so I defined a new which took three Nums. That was fine for implementing dot product and cross product and some simple tests, but when it came time to implement the + operator, I realized everything would be easier if there was a new which took an entire array of coordinates, and so added one.

Yesterday I realized that every operation was defined for any dimension except for cross product, which was only defined for 3D vectors. I did a google search and turned up a definition for 7D cross product. (More on that in a future post.) In the process of working on that, I figured I should define a new which took any number of scalar parameters and made a vector of that dimension. Luckily, Perl 6 defines slurpy array parameters, which take a variable number of scalars and give them to you as an array. Perfect for what I needed. This took the place of the 3D constructor, and I got rid of the Num limitation at the same time.

I've been toying with the idea of a constructor that takes a single Str and tries to parse it, with the idea that would be handy for unserialization. But on the other hand, it seems like the easiest way to serialize Perl 6 objects is to use the perl method. I haven't sorted this out yet in my head, so I haven't done anything with it.

General: I keep updating the Vector repo as I go. It's actually a few days ahead of where I've gotten with the blog posts. All comments and suggestions are welcome. I'm currently thinking I will try for posts on the cross product, the stringify method, testing it, and the overall philosophy of how this class might be used. And I'm thinking that if I have time, I may go on to try using it to define a non-uniform B-spline class...


  1. Just out of curiosity, is the $self necessary in your multi new? I thought there was a built in self keyword that returns the invocant?

  2. You're quite right! If I leave the "$self:" out of the signature, and change the "$self" in method body to just "self", it passes all my tests just fine.

    Like I said, I have no idea how the bless stuff works, I just blindly copied the new code from the spec and tweaked it until it worked.