If I were being accurate, this entry would actually be titled “What’s Wrong With Perl 5′s Overloading for People Who Care About Defensive Programming?” If you don’t care about defensive programming, then Perl 5′s overloading is perfect, and you can stop reading now. Also, please let me know so I can avoid working on code with you, thanks.

Defensive programming, for the purposes of this entry, can be defined as “checking sub/method arguments for sanity”. Yes, there’s more to it, but that’s where Perl 5′s overloading fails so badly.

Let’s say I’m writing an API that wants to take a filename as argument. What types of things might I expect? Well, obviously, I’d expect a string. More specifically, I’d expect a non-empty string, since q{} isn’t a valid filename. I could go further and even require a valid filename for my file system, but a non-empty string is a good baseline.

Enter Path::Class. This is a very handy module that gives you objects to represent directory and file names. It also uses Perl 5′s overloading to stringify when it’s used as a string. Genius, that’s exactly what I want.

So how exactly can I allow both strings and Path::Class::File objects as an argument? Well, I can start by checking if the argument has a string value. How do I do that, you ask? Well, you can’t, and that’s the problem! Everything in Perl stringifies, so if I pass any object, or any reference, or even undef, they will all turn into a string when used in a string context, although with undef I might get a warning.

In an ideal world, string-ishness would be represented as a method on an object, like as_string(). Unfortunately, Perl’s builtin types are not objects, so that’s right out. The only way that I know of to check if something can act as a string intentionally is the following hideous bit of code:

if (
    defined $val
    && ( !ref $val
        || ( blessed $val && overload::Method( $val, q{""} ) ) )
    ) {
    ...;
}

That’s a disgusting mouthful of gibberish. The turd cherry on top of that shit sundae of code is that the only way to accomodate overloading is to explicitly check for it. This completely violates the purpose of overloading, making things transparently act like builtin types!

There are alternatives. For example, I could check for a Path::Class::File object and use Moose’s coercion feature (along with MooseX::Params::Validate to coerce a bare string to an object. But if there’s some other class of object that stringifies as a file name then we have to coerce that explicitly, or use a union type.

This broken-ness really only applies to certain builtin operations, like stringification, numification, comparison, etc. The underlying problem is that all of Perl’s builtin types “work” with these operations. Other types of overloading, like overloading array dereferencing, are just fine. I can just write eval { @{ $val } } and if it works I know I have something that acts like an array reference.

This is, I think, fixed in Perl 6. It has an explicit API for typecasting so if a class wants to support stringification, it implements a Str() method. From what I can see, builtins like Array and Hash don’t implement this typecasting (yay). Good job Perl 6 team!

For now, I guess I’m stuck with the nastiness up above, or just throwing up my hands and saying “stringify your arguments your own damn self”.

I wanted to turn all the dates in my Changes file into the YYYY-MM-DD format (in this case from things like “Aug 27, 2008″). Here’s my one-liner:

perl -MDateTime::Format::Natural -pi -e \
    '$f = DateTime::Format::Natural->new;
     s/^([\d\.]+\s+)(\w+.+)$/$1 . $f->parse_datetime($2)->ymd/e' \
    Changes

The DateTime project is pretty badass, if I do say so myself. Note that most of the credit here should go to Steven Schubiger for DateTime::Format::Natural

After some recent conversations with Unny, CAA‘s Development Coordinator, I’ve started thinking about whether or not the idea of being vegan is a barrier to entry for animal advocacy.

Is vegan something I am, or is veganism simply something I do?

I’ve long said that “I am vegan” to people when describing my diet and/or my ethics. It’s a nice simple shorthand. However, it also defines me in a way that “living a vegan lifestyle” does not.

I’m not sure we should talk about veganism as part of one’s identity. This sort of framing may actually discourage people from making a change. Changing one’s self-identity is a big deal. On the other hand, asking someone to act on the feelings of compassion that they already have is much less of a big deal. Instead of telling that they need to change who they are, we are just acting them to change their behavior. Even better, we’re asking them to change their behavior so that it’s in accordance with their stated values.

At CAA, we’ve long taken a low-pressure approach of encouraging people to “explore veganism”. If someone tells us that they can’t become vegan, we encourage them to make whatever change they can. This change in framing seems like a natural extension of that “soft” approach.

The problem with all of this is that it’s incredibly awkward to not say “I’m vegan” in spoken conversation. Saying “I live a vegan lifestyle” just sounds weird. I can’t imagine that this language will be adopted. This is especially unlikely since the people who already have experienced a change in self-identity probably want to hold on to that identity!

However, I think that we can approach this sort of change slowly. For a beginning, we can look at the written materials we use to pursue animal activism, and modify them to emphasize that veganism is a matter of lifestyle, not identity. We can also make a point of describing things as vegan (food, clothes, etc.), not people.

Vegan Outreach has a great line in one of their essays, “we want a vegan world, not a vegan club.” I suspect that making veganism an identity furthers the creation of that club.