Lindsey Kuper (lindseykuper) wrote,
Lindsey Kuper
lindseykuper

Shield your eyes.

Hey! It's been a few hours since I complained about Perl! Okay, so I've got an arrayref, let's call it $stuff:

my $stuff = [];

Except, oh, wait, actually it's an attribute of a class that's been implemented using that Class::Std thing, so it's initialized like

my %stuff : ATTR;
$stuff{ $id } = [];

So, actually, %stuff is secretly a hash, except, shh, you didn't hear me say that, we're not supposed to have to care about that. We just have this arrayref that we can get at (for this particular class instance) with $stuff{ ident $self }. (Or $self->get_stuff(), if you like, but I'll come back to that.)

This all came up because I came across this code I couldn't read:

foreach my $thing ( @{ $stuff{ ident $self } } ){
	...
}

I stared at this for a while until I realized that the outer set of curly brackets around $stuff{ ident $self } weren't there as a hashref operator, but just as plain old block delimiters around the whole arrayref that was being dereferenced. Let's review: we've got curly brackets right next to each other, and they mean not only different things, but close to opposite things. It took me so long to puzzle out that I ended up showing it to Schwern to make sure I was thinking about it correctly. He said that I had it right, but added, "That part of dereferencing syntax is icky." If Schwern will admit to something being wrong with Perl, then that must really mean it's wrong!

What happens if we try to just write @$stuff{ ident $self }, without the delimiters? Apparently, the @ to the left makes the Perl parser try to chunk off "$stuff" by itself, and we get a compile-time error because Perl doesn't understand the symbol $stuff without its subscript attached.

So then I realized that, if we're good little "hey, look, my language can be object-oriented, too!" Perl programmers and we use a get_stuff() accessor instead of $stuff{ ident $self }, we can lose the inner set of curly brackets and make the whole thing a little nicer-looking and less ambiguous:

foreach my $thing ( @{ $self->get_stuff() } ){
	...
}

And that's what I ended up doing in the real thing. (But notice that we still need the curlies delimiting the whole arrayref, and this time, if we try to leave them out and just write @$self->get_stuff(), we don't even get a compile-time error; we just get a run-time error telling us that something isn't an arrayref. Oh, yeah, and Class::Std doesn't make the get_stuff() accessor method for us by default; we have to tell it to do that.)

Using the accessor method seemed like one of those Vaguely Good Ideas anyway, and realizing that it would also make my code more readable was a Ray Of Hope. 'Cause, see, I believe that one way to tell if you're Making Good Choices is that seemingly unrelated little things keep working out in unexpected, good ways. Conversely, if seemingly unrelated little things keep going wrong, then you need to back up and figure out where your Bad Choice was. At least, I really want to believe that this is the way the world works.

Tags: programming
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 13 comments