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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Vector | |
{ | |
has $.coordinates; | |
multi method new ($self: *@x) | |
{ | |
$self.bless(*, coordinates => @x); | |
} | |
multi method new ($self: @x) | |
{ | |
$self.bless(*, coordinates => @x); | |
} |
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...
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?
ReplyDeleteYou'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.
ReplyDeleteLike 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.